回答:
それらは非常に異なる方法で実装されます。
hash_map(unordered_mapTR1と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_mapC ++標準の新しいバージョンに追加されました。
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)の次数であると言っています。それは私には非常に奇妙ですが、それはそうです。