バイナリツリーは、実際のアプリケーションでハッシュテーブルよりも優れているのはいつですか?


7

私は現在、データ構造と基本的なアルゴリズムを利用しています。その一部がバイナリツリーです。私はアルゴリズムを理解し、二分探索木などを実装する方法を理解しています。O(log n)時間でルックアップを実行できるのは非常に賢明です。

しかし、ハッシュテーブルが同じ/より良い仕事をしないバイナリツリーを使用する場合の例を見つけるのに苦労しています。私は周りを検索していて、それが3Dグラフィスに使用されていることを発見しました。表示するアイテムについての何かですが、これに関連して苦労しています。

ハッシュテーブルよりもバイナリツリーを使用した方がよい例を教えてもらえますか?

回答:


14

ハッシュテーブルは、要素が存在するかどうかを通知するだけです。

これは、ハッシュテーブルでは実行できないバイナリツリーで実行できる処理です。

  • ソートされたツリーの全探索
  • 次に近い要素を見つける
  • 特定の値より小さいまたは大きいすべての要素を検索する

バイナリツリーの特別なプロパティを利用する実際のデータ構造の例については、Kdツリーに関するこのウィキペディアの記事を参照してください。 http://en.wikipedia.org/wiki/K-d_tree


1
また、最悪のサブリニアランタイム保証があります。
ラファエル

11

バイナリツリーの方が優れている、または特定の選択肢よりも簡単に調整できる1つのアプリケーションドメインは、永続的なデータ構造です((純粋に)関数型プログラミングでよく使用されます)。

永続データ構造は、変更されたときにそれ自体の以前のバージョンを保持するデータ構造です。(このプロパティを持たないデータ構造はエフェメラルと呼ばれます。)この種のデータ構造の1つの利点は、データ構造の一部を共有できることです-構造自体が変更されないことが保証されているため、安全に共有できます。他のデータ構造とスレッドの間を自由に変更できます。もう1つの主利点は、これらのデータ構造が推論しやすいことです。

概念的には、数値のリストである不変のデータ型を使用できます。たとえば、 L1={45}。次に、このリストの前に2つの数値を追加する新しい値を導入できます。L2=cos1cos2L1={1245}。何が起こったのL1?何もない-L1={45}、まだ。したL2これら3つの要素をコピーして、独自のリストに入れますか?理想的ではない-リストの値L1 属する L2、また:

1245L1L2

上記のような永続的なリストを実装するのにより適したデータ構造があります。同じように、バイナリツリーは、他のデータ構造や戦略よりも、特定のプロパティを持つ永続データ構造を実装するのに適しています。また、2つのリストを使用した例で示した構造的共有は、バイナリツリーに引き継がれます。ツリーのいくつかのバージョンが、共通のサブツリーを共有できることを想像できます。

私が言ったように、いくつかのデータ構造は永続的であるように修正する方が簡単です。あなたはハッシュテーブルについて言及します。これは通常(必ずしもそうでなくても)一時的なデータ構造です。ハッシュテーブルを永続的にするための一般的な実装戦略を調整する方法は、それほど明白ではないようです。ハッシュテーブルは、多くの場合、配列(具体的には、メモリの連続部分として実装される配列)で実装されることを考慮してください。配列は要素へのランダムアクセスを提供するので優れています。理想的には、O1ハッシュテーブル内の要素への平均アクセス。しかし、永続的なデータ構造を構築することに関しては、配列はそれほど良くありません。その要点は、不変の配列データ型を作成できる一方で、配列の性質上、多くのコピーを行わなければならないリスクがある-前述のList型が配列で実装されている場合、作成する必要があるリスクがあるということです。一部を共有するのではなく、5つの要素を持つまったく新しい配列。そして、もしあなたが配列の真ん中の何かを変更したい場合はどうでしょうか?最も明白な、そして避けられないように見える答えは、やはり、コピーです。

永続的なデータ構造では、一般にコピーを実行する必要はありません。ただし、特定のデータ構造ではコピーの頻度が低くなります。これは、データ構造を不変にする必要がある場合に望ましいプロパティです。


2番目から最後の段落で言及している永続配列の問題は、ClojureがJava配列を使用する代わりに大きなフラットツリーでランダムアクセスベクトルを実装する理由です。彼らは持っているOログ32 の代わりにアクセス時間 O1でも、構造を簡単に共有できます。
tsleyson 2014

1
Javaプログラムで純粋に機能的な赤黒木を使用して類似のビットセットを多数格納したことがありました。これにより、メモリ使用量が大幅に削減され、Jaccard類似度係数をすばやく計算できました。このようなツリーは、ハッシュを維持することで(不等)について効率的に比較することもできます。たとえば、各ノードにそのブランチのハッシュのXORを格納させることにより、これは、ローテーションを維持するのは簡単です。
jkff 2014

4

バイナリツリーには、特にバイナリ検索ツリーだけでなく、すべてのバイナリツリーを含める場合、多くのアプリケーションがあります。ヒープは、最上位の要素がすべての要素の最小値または最大値のいずれかであるバイナリツリーとして実装されます。これは、優先度キューを必要とするシナリオに非常に役立ちます。

ハッシュマップは、要素の存在を確認するだけの一連の操作で非常に効率的です。しかし、順序付けまたはソートされたデータに対して存在しないチェック操作を実行することに関しては、それらは弱いです。さらに、ハッシュアルゴリズムを調整することで可能になりますが、バイナリツリーは部分的なキー検索の概念をより適切にサポートするようです。たとえば、文字列のバイナリツリーを使用して、「an」で始まる単語に回答しようとすることができます。トライが与えられた場合、そのタイプのシナリオにはより良いデータ構造になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.