これでstd
実際のハッシュマップが作成されましたが、実際に存在するシステムで古きunordered_map
良きものを使用したいのはなぜですか(またはいつ) ?すぐには見えない明らかな状況はありますか?map
unordered_map
5 に答える
すでに述べたようmap
に、ソートされた方法で要素を反復処理することはできますが、できunordered_map
ません。これは、コレクション(名簿など)の表示など、多くの状況で非常に重要です。これは、次のような他の間接的な方法でも現れます。(1)によって返されたイテレータから反復を開始するfind()
、または(2)のようなメンバー関数の存在lower_bound()
。
また、最悪の場合の 検索の複雑さにも多少の違いがあると思います。
の場合
map
、O(lg N)です。の場合
unordered_map
、それはO(N)です[これは、ハッシュ関数が適切でなく、ハッシュの衝突が多すぎる場合に発生する可能性があります。]
最悪の場合の 削除の複雑さにも同じことが当てはまります。
上記の回答に加えて、unordered_map
一定の速度( )であるからといって、 (の順序)O(1)
よりも速いという意味ではないことにも注意してください。2 32(または2 64 )によって制限されるため、定数は特により大きくなる可能性があります。map
log(N)
log(N)
N
したがって、他の回答(map
順序の維持とハッシュ関数が難しい場合があります)に加えて、map
よりパフォーマンスが高い可能性があります。
たとえば、私がブログ投稿のために実行したプログラムでは、VS10の方std::unordered_map
が遅いことがわかりましたstd::map
(ただしboost::unordered_map
、両方よりも高速でした)。
3番目から5番目の小節に注意してください。
これは、CppCon2014の講義でのGoogleのChandlerCarruthによるものです。
std::map
(多くの人が考えているように)パフォーマンス指向の作業には役立ちません。O(1)償却アクセスが必要な場合は、適切な連想配列を使用します(または、1つがない場合std::unorderded_map
)。ソートされたシーケンシャルアクセスが必要な場合は、ベクトルに基づいたものを使用してください。
また、std::map
バランスの取れたツリーです。そして、あなたはそれをトラバースするか、信じられないほど頻繁にバランスを取り直す必要があります。これらはそれぞれキャッシュキラー操作とキャッシュ黙示録操作です...だから、NOと言ってstd::map
ください。
効率的なハッシュマップの実装に関するこのSOの質問に興味があるかもしれません。
(PS-std::unordered_map
リンクリストをバケットとして使用するため、キャッシュに適していません。)
std::map
マップ内のアイテムをソートされた順序で反復処理するために必要なものを使用することは明らかだと思います。
ハッシュ関数(一般的に非常に直感的ではない)の代わりに、比較演算子(直感的)を記述したい場合にも使用できます。
非常に大きなキー、おそらく大きな文字列があるとします。大きな文字列のハッシュ値を作成するには、文字列全体を最初から最後まで調べる必要があります。キーの長さまで少なくとも線形の時間がかかります。ただし、キーの演算子を使用してバイナリツリーのみを検索する>
場合、最初の不一致が見つかったときに各文字列比較が返される可能性があります。これは通常、大きな文字列の場合は非常に早いです。
この推論は、とのfind
関数に適用できます。キーの性質が、(の場合)バイナリ検索を使用して要素の場所を見つけるのにかかる時間よりも(の場合)ハッシュの生成に時間がかかるようなものである場合、キーの検索はより高速であるはずです。で。これが当てはまるシナリオを考えるのは非常に簡単ですが、実際には非常にまれであると私は信じています。std::unordered_map
std::map
std::unordered_map
std::map
std::map