ハッシュテーブルとバイナリツリー


30

辞書を実装する場合(「顧客IDで顧客データを検索したい」)、使用される一般的なデータ構造はハッシュテーブルとバイナリ検索ツリーです。たとえば、C ++ STLライブラリは(バランスのとれた)バイナリ検索ツリーを使用して辞書(マップと呼びます)を実装し、.NETフレームワークは内部でハッシュテーブルを使用することを知っています。

これらのデータ構造の長所と短所は何ですか?特定の状況で合理的な他のオプションはありますか?

キーが強力な基礎構造を持っている場合、たとえば、キーがすべて1からnまでの整数である場合など、特に興味がないことに注意してください。


1
私はあなたを怒らせますが、「1からnの間の整数」と言うことはできません。その場合、配列は他のすべてのデータ構造を追い越すからです:-)。「文字列」は公平で、ほとんどの状況をカバーしています。
jmad

@jmadは彼がそのケースに興味がないと言った。
ジョー

@ジョー私はこれを考慮に入れたことが明らかだと思った。とにかく、それはキーの最悪の例を挙げる理由ではありません。
jmad

1
実際には、.NETには、ツリーを使用して実装された辞書とハッシュテーブルを使用して実装された辞書の両方があります(2011年以降のC ++も同様です)。
sepp2k

回答:


26

このトピックについては、論文全体を書くことができます。いくつかの重要なポイントを取り上げるだけで、他のデータ構造の議論は最小限に抑えます(実際には多くのバリアントがあります)。この答え全体を通して、は辞書内のキーの数です。n

簡単な答えは、ほとんどの場合ハッシュテーブルは高速ですが、最悪の場合は非常に悪いことです。検索ツリーには、最悪の場合の振る舞い抑えるなど、多くの利点がありますが、通常の場合はやや遅くなります。

Olgnlog2n

ハッシュテーブルはもう少し変数です。約ポインターの配列が必要です。1つの要素へのアクセスは、ハッシュ関数の品質に依存します。ハッシュ関数の目的は、要素を分散させることです。ハッシュテーブルに格納するすべての要素に異なるハッシュがある場合、ハッシュテーブルは「機能します」。この場合、基本的な操作(ルックアップ、挿入、削除)は、かなり小さい定数(1つのハッシュ計算と1つのポインタールックアップ)でO 1 時間かかります。これにより、多くの典型的なケースでハッシュテーブルが非常に高速になります。2nO1

ハッシュテーブルの一般的な問題は、複雑さが保証されないことです。O1

  • On
  • O1

あなたが投げるときは、データの局所性をミックスに、ハッシュテーブルは不十分行います。これらは関連する要素を遠くに保存するため正確に機能します。つまり、アプリケーションがプレフィックスを順番に共有する要素を検索する場合、キャッシュ効果の恩恵は受けません。アプリケーションが本質的にランダムなルックアップを行う場合、これは関係ありません。

検索ツリーを支持するもう1つの要因は、それらが不変のデータ構造であることです。ツリーのコピーを取り、その中のいくつかの要素を変更する必要がある場合、データ構造のほとんどを共有できます。ハッシュテーブルのコピーを取得する場合は、ポインターの配列全体をコピーする必要があります。また、純粋に機能的な言語で作業している場合、ハッシュテーブルは多くの場合オプションではありません。

k1k2hk1=hk2

特に、キーをアルファベット順に並べたい場合など、キーの順序が必要な場合は、ハッシュテーブルは役に立ちません(ソートする必要があります)検索ツリーを順番に簡単にたどることができます。

ハッシュツリーの形式でバイナリ検索ツリーとハッシュテーブルを組み合わせることができます。ハッシュツリーは、ハッシュに従ってキーを検索ツリーに格納します。これは、たとえば、計算が簡単な順序関係を持たないデータで作業する純粋に機能的なプログラミング言語で役立ちます。

キーが文字列(または整数)の場合、トライは別のオプションになります。トライはツリーですが、検索ツリーとは異なるインデックスが付けられています。キーをバイナリで記述し、0で左に1で右に移動します。したがって、アクセスのコストはキーの長さに比例します。トライを圧縮して中間ノードを削除できます。これは、パトリシアトライまたは基数ツリーとして知られています。特に多くのキーが共通のプレフィックスを共有している場合、基数ツリーはバランスのとれたツリーよりも優れています。


2
BSTにもデータのローカリティがありませんか?
svick

@svickノードがどのように割り当てられているかに応じて、ノードは割り当てられる場合とされない場合があります。ツリーのアリティを増やすと、実行時間を犠牲にすることなく役立ちます(コストが大きくなり、コードが複雑になります)。
ジル 'SO-悪であるのをやめる

2
BSTでは、要素を「順番どおりに」取得するのは簡単です。ハッシュテーブルの場合は問題外です。
フォンブランド

セキュリティ上の理由を除いて、ハッシュテーブルの平均ケースがバイナリツリーのケースよりも優れている場合、ハッシュテーブルに最悪の最悪時間が存在する場合、なぜ重要なのでしょうか。ユーティリティ/ユーザーの利便性は、ツリーが終了するまでの時間とほぼ線形の関係にあるため、予想される(平均)値がすべてであるべきだと思います。
ケルミクラ

@ Kyth'Py1k「終わりのツリー」とはどういう意味ですか?ハッシュテーブルのポイントは、ツリー全体ではなく、一度に1つの値にアクセスすることです。そうしないと、リストまたは配列の方が適切に機能します。平均値が重要な状況(リアルタイム制約がある場合など、常にそうとは限らない)でも、特定の状況で行われたリクエストの平均であり、多くの場合、テーブル全体で均一ではありません—たとえば、特定のプレフィックスにバイアスをかけます。
ジル 'SO-悪であるのをやめる'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.