回答:
それらは非常に異なる方法で実装されます。
hash_map
(unordered_map
TR1とBoostでは、代わりにそれらを使用します)ハッシュテーブルを使用します。キーはテーブルのスロットにハッシュされ、値はそのキーに関連付けられたリストに格納されます。
map
バランスのとれた二分探索木(通常は赤/黒木)として実装されます。
unordered_map
は、コレクションの既知の要素にアクセスするためのパフォーマンスが若干向上するはずmap
ですが、便利な特性が追加されます(たとえば、ソートされた順序で格納されるため、最初から最後まで走査できます)。 unordered_map
挿入および削除の方がmap
。より高速です。
hash_map
多くのライブラリ実装によって提供される共通の拡張機能でした。これがunordered_map
、TR1の一部としてC ++標準に追加されたときに名前が変更された理由です。mapは通常、赤黒ツリーのようなバランスの取れたバイナリツリーで実装されます(実装はもちろん異なります)。 hash_map
そしてunordered_map
一般的にハッシュテーブルで実装されています。したがって、順序は維持されません。 unordered_map
挿入/削除/クエリはO(1)(一定時間)となり、マップはO(log n)となります。nはデータ構造内のアイテム数です。したがってunordered_map
、より高速であり、アイテムの順序を気にしない場合は、を優先する必要がありますmap
。順序を維持したい場合があります(キーで並べ替え)map
。そのための選択です。
主な違いのいくつかは、複雑さの要件にあります。
A map
はO(log(N))
赤黒ツリーデータ構造として実装されているため、挿入および検索操作に時間がかかります。
アンはunordered_map
の「平均」の時間が必要ですO(1)
挿入と発見のために、しかし、最悪のケースの時間を持つことが許されますO(N)
。これは、ハッシュテーブルのデータ構造を使用して実装されているためです。
そのため、通常はunordered_map
より高速になりますが、格納するキーとハッシュ関数によっては、さらに悪化する可能性があります。
C ++仕様では、STLコンテナーに使用する必要があるアルゴリズムを正確に示していません。ただし、そのパフォーマンスには一定の制約がmap
あり、他の連想コンテナ用のハッシュテーブルの使用は除外されます。(これらは最も一般的には赤/黒ツリーで実装されます。)これらの制約は、ハッシュテーブルが提供できるよりも、これらのコンテナーに対してより良い最悪の場合のパフォーマンスを必要とします。
ただし、多くの人は本当にハッシュテーブルを必要としています。そのため、ハッシュベースのSTL連想コンテナは、長年にわたって一般的な拡張機能でした。その結果、unordered_map
C ++標準の新しいバージョンに追加されました。
map
一般的にバランスのとれたbtree である理由は、operator<()
位置を決定する手段としてを使用したためだと思いました。
map
内のすべてのメンバーがソートされ、マップも同様であるため、balanced binary search tree
(通常はrb_tree
)から実装されbalanced binary search tree
ます。
hash_map
から実装されていhashtable
ます。すべてのメンバーhashtable
はソートされていないため、メンバーはソートされhash_map(unordered_map)
ていません。
hash_map
はc ++標準ライブラリではありませんが、名前が変更されunordered_map
(名前が変更されたと考えることができます)、c ++ 11がこの質問を参照するため、c ++標準ライブラリになります。hash_mapとunordered_mapの違いは?詳細については。
以下では、2つの型のマップがどのように実装されているかについてのソースコードからいくつかのコアインターフェイスを提供します。
以下のコードは、mapがのラッパーにbalanced binary search tree
すぎないことを示していbalanced binary search tree
ます。ほぼすべての関数は、関数を呼び出すだけです。
template <typename Key, typename Value, class Compare = std::less<Key>>
class map{
// used for rb_tree to sort
typedef Key key_type;
// rb_tree node value
typedef std::pair<key_type, value_type> value_type;
typedef Compare key_compare;
// as to map, Key is used for sort, Value used for store value
typedef rb_tree<key_type, value_type, key_compare> rep_type;
// the only member value of map (it's rb_tree)
rep_type t;
};
// one construct function
template<typename InputIterator>
map(InputIterator first, InputIterator last):t(Compare()){
// use rb_tree to insert value(just insert unique value)
t.insert_unique(first, last);
}
// insert function, just use tb_tree insert_unique function
//and only insert unique value
//rb_tree insertion time is : log(n)+rebalance
// so map's insertion time is also : log(n)+rebalance
typedef typename rep_type::const_iterator iterator;
std::pair<iterator, bool> insert(const value_type& v){
return t.insert_unique(v);
};
hash_map
:hash_map
実施されhashtable
、その構造多少このようなものです:
以下のコードでは、の主要部分を指定してhashtable
から、を指定しますhash_map
。
// used for node list
template<typename T>
struct __hashtable_node{
T val;
__hashtable_node* next;
};
template<typename Key, typename Value, typename HashFun>
class hashtable{
public:
typedef size_t size_type;
typedef HashFun hasher;
typedef Value value_type;
typedef Key key_type;
public:
typedef __hashtable_node<value_type> node;
// member data is buckets array(node* array)
std::vector<node*> buckets;
size_type num_elements;
public:
// insert only unique value
std::pair<iterator, bool> insert_unique(const value_type& obj);
};
map's
だけのメンバーのようrb_tree
に、hash_map's
唯一のメンバーはhashtable
です。以下のようなメインコードです:
template<typename Key, typename Value, class HashFun = std::hash<Key>>
class hash_map{
private:
typedef hashtable<Key, Value, HashFun> ht;
// member data is hash_table
ht rep;
public:
// 100 buckets by default
// it may not be 100(in this just for simplify)
hash_map():rep(100){};
// like the above map's insert function just invoke rb_tree unique function
// hash_map, insert function just invoke hashtable's unique insert function
std::pair<iterator, bool> insert(const Value& v){
return t.insert_unique(v);
};
};
以下の画像は、hash_mapに53のバケットがあり、いくつかの値を挿入する場合を示しています。これは内部構造です。
以下の画像は、mapとhash_map(unordered_map)の違いを示しています。:
何が得られるのかわかりませんが、hash_mapは、150Kの符号なし整数キーと浮動小数点値をclear()するのに20秒以上かかります。私はただ実行して、他の誰かのコードを読んでいます。
これは、hash_mapを含める方法です。
#include "StdAfx.h"
#include <hash_map>
私はこれをここで読んだ https://bytes.com/topic/c/answers/570079-perfomance-clear-vs-swap
clear()はO(N)の次数であると言っています。それは私には非常に奇妙ですが、それはそうです。