首先拉动的数据结构 - 免费 - java

时间:2013-02-06 19:14:40

标签: data-structures map

我正在寻找具有下一个功能的数据结构: - 有钥匙和价值 - 可以在O(n)中找到值> t> O(logn)或O(1) - 可以拉出我插入的第一个元素和最后一个元素。

TreeMep不好,因为如果我插入键(作为字符串)“b”然后键入“a”如果我将拉出第一个,我将得到“a”而不是“b”

ConcurrentSkipListMap不好,因为我不能依赖size func'

非常感谢任何帮助

感谢

1 个答案:

答案 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