Pythonがハッシュテーブルを使用してdictを実装しますが、Red-Black Treeは使用しないのはなぜですか?
キーは何ですか?パフォーマンス?
Pythonがハッシュテーブルを使用してdictを実装しますが、Red-Black Treeは使用しないのはなぜですか?
キーは何ですか?パフォーマンス?
回答:
これは、Python固有ではない一般的な回答です。
| Hash Table | Red-Black Tree |
-------+-------------+---------------------+
Space | O(n) : O(n) | O(n) : O(n) |
Insert | O(1) : O(n) | O(log n) : O(log n) |
Fetch | O(1) : O(n) | O(log n) : O(log n) |
Delete | O(1) : O(n) | O(log n) : O(log n) |
| avg :worst | average : worst |
ハッシュテーブルの問題は、ハッシュが衝突する可能性があることです。衝突を解決するためのさまざまなメカニズムがあります。たとえば、オープンアドレス指定や個別の連鎖などです。絶対的な最悪のケースは、すべてのキーが同じハッシュコードを持っていることです。この場合、ハッシュテーブルはリンクリストに劣化します。
他のすべての場合、ハッシュテーブルは実装が簡単で優れたパフォーマンスを提供する優れたデータ構造です。欠点は、テーブルをすばやく成長させてエントリを再配布できる実装は、実際に使用されているメモリとほぼ同じ量のメモリを浪費する可能性が高いことです。
RBツリーは自己均衡型であり、最悪の場合にアルゴリズムの複雑さを変更しません。ただし、実装はより困難です。また、それらの平均的な複雑さは、ハッシュテーブルの複雑さよりも悪いです。
ハッシュテーブル内のすべてのキーはハッシュ可能で、相互の同等性が比較可能でなければなりません。これは、文字列または整数では特に簡単ですが、ユーザー定義型に拡張することもかなり簡単です。Javaのような一部の言語では、これらのプロパティは定義により保証されています。
RB-Treeのキーには完全な順序が必要です。各キーは他のキーと比較可能でなければならず、2つのキーはより小さい、より大きい、または等しいかを比較する必要があります。この順序付けの等価性は、セマンティックの等価性と同等でなければなりません。これは整数や他の数値については簡単で、文字列についても非常に簡単です(順序は一貫している必要があり、外部からは観察できないため、順序はロケールを考慮する必要はありません[1])。 。それらの間の何らかの比較が可能でない限り、異なるタイプのキーを持つことは絶対に不可能です。
[1]:実際、ここは間違っています。2つの文字列はバイトが等しくない場合がありますが、一部の言語の規則に従っては同等です。たとえば、2つの等しい文字列のエンコード方法が異なる1つの例については、Unicode正規化を参照してください。Unicode文字の構成がハッシュキーにとって重要であるかどうかは、ハッシュテーブルの実装が知ることができないものです。
RBツリーキーの安価な解決策は、最初に同等性をテストし、次に同一性を比較する(つまり、ポインターを比較する)と考えられるかもしれません。ただし、この順序は推移的ではありません。if a == b
およびの場合id(a) > id(c)
、それに続く必要がありますがid(b) > id(c)
、ここでは保証されません。そのため、代わりに、キーのハッシュコードをルックアップキーとして使用できます。ここでは、順序付けは正しく機能しますが、RBツリー内の同じノードに割り当てられる、同じハッシュコードを持つ複数の個別のキーになる可能性があります。これらのハッシュの衝突を解決するために、ハッシュテーブルと同様に個別のチェーンを使用できますが、これはハッシュテーブルの最悪の場合の動作、つまり両方の最悪の動作も継承します。
ハッシュテーブルは本質的に単なる配列であるため、ハッシュテーブルはツリーよりもメモリの局所性が優れていると考えています。
両方のデータ構造のエントリには、かなり高いオーバーヘッドがあります。
RBツリーでの挿入と削除には、ツリーの回転が含まれます。これらは実際には高価ではありませんが、オーバーヘッドが発生します。ハッシュでは、挿入と削除は単純なアクセスよりも高価ではありません(ただし、挿入時にハッシュテーブルのサイズを変更するのはO(n)
努力です)。
ハッシュテーブルは本質的に可変ですが、RBツリーは不変の方法で実装することもできます。ただし、これはほとんど役に立ちません。
真実である可能性のあるさまざまな理由がありますが、主な理由は次のとおりです。
記述/保守が簡単で、一般的な使用例でパフォーマンスが勝者ですか?サインアップしてください!