我正在寻找具有下一个功能的数据结构: - 有钥匙和价值 - 可以在O(n)中找到值> t> O(logn)或O(1) - 可以拉出我插入的第一个元素和最后一个元素。
TreeMep不好,因为如果我插入键(作为字符串)“b”然后键入“a”如果我将拉出第一个,我将得到“a”而不是“b”
ConcurrentSkipListMap不好,因为我不能依赖size func'
非常感谢任何帮助
感谢
答案 0 :(得分:0)
您可以使用deque
(双端队列)与multimap
(简称二进制搜索树)交叉引用,这允许重复键。
队列的每个元素都有一个引用(迭代器)到映射的相应元素,反之亦然。
这样,你可以在O(log N)中搜索地图,你可以在O(log N)中按序列的两端推/拉。
您可以决定将字符串存储在地图或队列中。
这是C ++中的一个实现:
#include <string>
#include <map>
#include <deque>
typedef int my_key_type; // Key type
typedef std::string my_value_type; // Value type
struct queueitem; // Queue element
typedef std::deque<queueitem> my_queue; // Queue
typedef std::multimap <my_key_type,
my_queue::iterator> my_map; // Map
typedef std::pair <my_key_type,
my_queue::iterator> my_map_pair; // Map element
struct queueitem
{
my_value_type value;
my_map::iterator mapitem;
queueitem (const my_value_type & val) : value(val) {}
};
class mapqueue
{
public:
mapqueue () {}
my_value_type find (my_key_type key) const;
size_t index_of (my_key_type key) const;
my_value_type front_value () const { return Q.front().value; }
my_value_type back_value () const { return Q.back().value; }
my_key_type front_key () const
{ return Q.front().mapitem->first; }
my_key_type back_key () const
{ return Q.back().mapitem->first; }
void push_front (my_key_type key,
const my_value_type & value);
void push_back (my_key_type key,
const my_value_type & value);
void pop_front ();
void pop_back ();
private:
my_queue Q;
my_map M;
mapqueue (const mapqueue &) {}
mapqueue & operator= (const mapqueue &) { return *this; }
};
using namespace std;
my_value_type mapqueue::find (my_key_type key) const
{
my_map::const_iterator it = M.find (key);
if (it==M.end())
throw "Not found";
return it->second->value;
}
size_t mapqueue::index_of (my_key_type key) const
{
my_map::const_iterator it = M.find (key);
if (it==M.end())
throw "Not found";
return it->second - Q.begin();
}
void mapqueue::push_front (my_key_type key,
const my_value_type & value)
{
Q.push_front (queueitem(value));
my_queue::iterator qit = Q.begin ();
qit->mapitem = M.insert (my_map_pair(key,qit));
}
void mapqueue::push_back (my_key_type key,
const my_value_type & value)
{
Q.push_back (queueitem(value));
my_queue::iterator qit = Q.end () - 1;
qit->mapitem = M.insert (my_map_pair(key,qit));
}
void mapqueue::pop_front ()
{
M.erase (Q.front().mapitem);
Q.pop_front ();
}
void mapqueue::pop_back ()
{
M.erase (Q.back().mapitem);
Q.pop_back ();
}
这也支持在O(log N)中查找任何给定键的队列中的索引。如果您不需要,可以简化在地图中存储字符串的设计,并将地图中的引用移除到队列中。
更新:现在通过typedef
指定键和值类型。这样就很容易改变它们。在由这两种类型参数化的模板中转换整个事物会很有趣。这样,即使在同一程序中,相同的代码也可以重用于不同的键值类型对。
更新:通用案例有一个工具:Boost Multi-index Containers Library。请参阅文档中的this example。