(通常はバイナリ検索ツリー)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
sで指定されるようになりました。このように、それらを変更するのは簡単です。これらの2つのタイプによってパラメーター化されたテンプレートですべてを変換することは興味深いでしょう。このように、同じプログラム内であっても、同じコードをKey-Valueタイプの異なるペアに再利用できます。
更新:一般的な場合のツールがあります: Boost Multi-indexContainersLibrary。ドキュメントのこの例を参照してください。