そのため、ハッシュテーブルまたはプレフィクスツリーのどちらかを選択する必要がある場合、どちらを選択するかを決定する要因は何ですか。私自身の素朴な観点から、トライを使用すると配列として保存されないため、余分なオーバーヘッドがありますが、実行時間の観点では(最長のキーが最長の英語の単語であると仮定して)、本質的に= O(1)(上限に関連して)。おそらく最も長い英語の単語は50文字ですか?
ハッシュテーブルは即座に検索されますインデックスを取得したら。ただし、キーをハッシュしてインデックスを取得すると、50ステップ近くを簡単に実行できるように思えます。
誰かがこれについてより経験豊富な視点を提供できますか?ありがとう!
試行の利点:
基礎:
新しい操作:
リンク構造の利点:
ハッシュテーブルの利点:
それはすべてあなたが解決しようとしている問題に依存します。挿入と検索だけが必要な場合は、ハッシュテーブルを使用します。プレフィックス関連のクエリなど、より複雑な問題を解決する必要がある場合は、トライがより良い解決策である可能性があります。
誰もがハッシュテーブルとその使用法を知っていますが、それは正確に一定のルックアップ時間ではなく、ハッシュテーブルの大きさ、ハッシュ関数の計算の複雑さに依存します。
効率的なルックアップのために巨大なハッシュテーブルを作成することは、小さなレイテンシ/スケーラビリティが重要な産業シナリオ(たとえば、高頻度の取引)のほとんどでエレガントなソリューションではありません。キャッシュミスを減らすには、メモリ内で占有するスペースに対して最適化されるデータ構造に注意する必要があります。
トライが要件により適している非常に良い例は、メッセージングミドルウェアです。さまざまなカテゴリのメッセージのサブスクライバーおよびパブリッシャー(JMSの用語-トピックまたは交換)が100万人いる場合、トピック(実際は文字列)に基づいてメッセージをフィルターで除外する場合は、ハッシュテーブルを作成する必要はありません100万のトピックを持つ100万のサブスクリプションのために。より良いアプローチは、トピックをトライで保存することです。そのため、トピックの一致に基づいてフィルタリングが行われる場合、その複雑さはトピック/サブスクリプション/パブリッシャーの数に依存しません(文字列の長さにのみ依存します)。スペースの要件を最適化するためにこのデータ構造を使用して創造性を高め、キャッシュミスを減らすことができるため、気に入っています。
ツリーを使用する:
誰も明示的に言及していないが、心に留めておくことが重要だと思うものがあります。ハッシュテーブルとさまざまな種類の試行の両方に、通常O(k)
操作があります。ここで、k
は文字列の長さ(ビット単位、または同等の文字単位)です。
これは、適切なハッシュ関数があることを前提としています。 「農場」と「農場の動物」を同じ値にハッシュしたくない場合、ハッシュ関数はキーのすべてのビットを使用する必要があるため、「農場の動物」のハッシュには約2倍の時間がかかります「農場」(何らかのローリングハッシュシナリオを使用している場合を除きますが、操作を節約するためのいくつかのシナリオも試行されます)。そして、バニラの試みで、「農場の動物」を挿入するのに「農場」の約2倍の時間がかかるのは明らかです。長期的には、圧縮された試行でも同様です。
トライへの挿入とルックアップは、入力文字列O(s)の長さと線形です。
ハッシュは、ルックアップと挿入のためにO(1)を提供しますが、最初に再びO(s)である入力文字列に基づいてハッシュを計算する必要があります。
結論として、漸近的な時間の複雑さはどちらの場合も線形です。
トライにはデータの観点からいくつかのオーバーヘッドがありますが、圧縮されたトライを選択すると、ハッシュテーブルとほぼ同程度になります。
ネクタイを破るには、この質問を自問してください:完全な単語だけを検索する必要がありますか?または、プレフィックスに一致するすべての単語を返す必要がありますか? (予測テキスト入力システムと同様)。最初のケースでは、ハッシュを探します。よりシンプルでクリーンなコードです。テストと保守がより簡単に。接頭辞または接尾辞が重要である、より詳細な使用例については、試してみてください。
そして、もしあなたが楽しみのためにそれをするなら、トライを実装することは日曜日の午後を有効に使うでしょう。
HashTable実装は、基本的なTrie実装と比較してスペース効率が高くなります。しかし、文字列では、ほとんどの実際のアプリケーションで順序付けが必要です。ただし、HashTableは辞書的な順序を完全に乱します。アプリケーションが辞書式順序(部分検索、特定のプレフィックスを持つすべての文字列、すべての単語を並べ替えられた順序など)に基づいて操作している場合、トライを使用する必要があります。ルックアップのみの場合、HashTableを使用する必要があります(ほぼ間違いなく、最短のルックアップ時間を提供します)。
P.S.:これら以外に、三項探索木(TST)が優れた選択肢です。ルックアップ時間はHashTableよりも長くなりますが、他のすべての操作では時間効率が高くなります。また、試行よりもスペース効率が高くなります。