私の質問は、トライのデータ構造と基数トライが同じものであるかどうかです。
つまり、いいえ。カテゴリ基数トライは、特定のカテゴリの説明トライを、それは、すべての試行が基数試行であることを意味するものではありません。
それらが同じでない場合、Radixトライ(別名Patriciaトライ)の意味は何ですか?
私はあなたが書くつもりだったのはあなたの質問には含まれていないと思います。
同様に、PATRICIAは特定のタイプの基数トライを示しますが、すべての基数試行がPATRICIA試行であるとは限りません。
トライとは何ですか?
「Trie」は、連想配列として使用するのに適したツリーデータ構造を記述します。ブランチまたはエッジはキーの一部に対応します。部分の定義はここではかなり曖昧です。これは、試行の実装が異なると、エッジに対応するために異なるビット長を使用するためです。たとえば、バイナリトライには、ノードごとに2つのエッジがあり、0または1に対応します。一方、16ウェイトライには、ノードごとに4つのビット(または16進数字:0x0〜0xf)に対応する16のエッジがあります。
Wikipediaから取得したこの図は、(少なくとも)キー「A」、「to」、「tea」、「ted」、「ten」、「inn」が挿入されたトライを描いているようです。
このトライがキー「t」、「te」、「i」、または「in」のアイテムを格納する場合、各ノードに追加情報が存在して、nullaryノードと実際の値を持つノードを区別する必要があります。
基数トライとは何ですか?
"Radix trie"は、Ivaylo Strandjevが彼の回答で述べたように、一般的な接頭辞部分を凝縮するトライの形式を説明しているようです。次の静的割り当てを使用して、キー「smile」、「smiled」、「smiles」、および「smiling」にインデックスを付ける256方向のトライがあるとします。
root['s']['m']['i']['l']['e']['\0'] = smile_item;
root['s']['m']['i']['l']['e']['d']['\0'] = smiled_item;
root['s']['m']['i']['l']['e']['s']['\0'] = smiles_item;
root['s']['m']['i']['l']['i']['n']['g']['\0'] = smiling_item;
各添え字は内部ノードにアクセスします。つまりsmile_item
、を取得するには、7つのノードにアクセスする必要があります。8つのノードアクセスはsmiled_item
およびsmiles_item
に対応し、9つはに対応しますsmiling_item
。これらの4つのアイテムの場合、合計14のノードがあります。ただし、これらはすべて最初の4バイト(最初の4つのノードに対応)が共通しています。これらの4バイトを圧縮して、root
に対応するを作成します。これは基数トライです。['s']['m']['i']['l']
、4つのノードアクセスが最適化されます。これは、メモリとノードアクセスが少ないことを意味します。これは非常に良い指標です。最適化を再帰的に適用して、不要なサフィックスバイトにアクセスする必要性を減らすことができます。最終的に、トライによってインデックスが付けられた場所で、検索キーとインデックス付きキーの違いのみを比較するようになります。
root = smil_dummy;
root['e'] = smile_item;
root['e']['d'] = smiled_item;
root['e']['s'] = smiles_item;
root['i'] = smiling_item;
アイテムを取得するには、各ノードに位置が必要です。「smiles」の検索キーとroot.position
4のa を使用してroot["smiles"[4]]
、にアクセスしますroot['e']
。これをという変数に格納しますcurrent
。current.position
差の位置である、5 "smiled"
及び"smiles"
ので、次のアクセスがされますroot["smiles"[5]]
。これでsmiles_item
、および文字列の終わりに到達します。検索が終了し、アイテムが取得されました。ノードアクセスは8回ではなく3回です。
パトリシアトライとは何ですか?
PATRICIAトライは、基数トライのバリアントでありn
、n
アイテムの格納に使用されるノードのみが存在する必要があります。上記の我々の粗実証基数トライ擬似コードでは、合計で5つのノードがある:root
(引数なしのノードであり、それは実際の値を含まない)、 、、root['e']
および。パトリシアトライでは、4つしかありません。PATRICIAはバイナリアルゴリズムであるため、これらのプレフィックスがバイナリでどのように異なるかを見てみましょう。root['e']['d']
root['e']['s']
root['i']
smile: 0111 0011 0110 1101 0110 1001 0110 1100 0110 0101 0000 0000 0000 0000
smiled: 0111 0011 0110 1101 0110 1001 0110 1100 0110 0101 0110 0100 0000 0000
smiles: 0111 0011 0110 1101 0110 1001 0110 1100 0110 0101 0111 0011 0000 0000
smiling: 0111 0011 0110 1101 0110 1001 0110 1100 0110 1001 0110 1110 0110 0111 ...
上記の順序でノードが追加されると考えてみましょう。smile_item
この木の根です。違いを見つけやすくするために太字になっている違いは"smile"
、ビット36のの最後のバイトです。この時点まで、すべてのノードに同じプレフィックスが付いています。smiled_node
に属していsmile_node[0]
ます。差"smiled"
とは"smiles"
ビット43で起こる"smiles"
ので、「1」ビットを有しsmiled_node[1]
ていますsmiles_node
。
NULL
ブランチとして使用したり、検索がいつ終了したかを示す追加の内部情報を使用したりするのではなく、ブランチはツリーのどこかにリンクし、テストするオフセットが増加するのではなく減少すると検索が終了します。以下は、このようなツリーの簡単な図です(パトリシアは、実際にはツリーというより、循環グラフに近いものです)。
さまざまな長さのキーを含むより複雑なPATRICIAアルゴリズムが可能ですが、PATRICIAの技術的特性の一部はプロセスで失われます(つまり、どのノードにもその前のノードとの共通のプレフィックスが含まれています)。
このように分岐することには、いくつかの利点があります。すべてのノードに値が含まれます。これにはルートが含まれます。その結果、コードの長さと複雑さは、実際にはかなり短くなり、おそらく少し速くなります。アイテムを見つけるために、少なくとも1つのブランチと多くてもk
ブランチ(k
検索キーのビット数)をたどります。ノードはそれぞれ2つだけのブランチを格納するため、非常に小さく、キャッシュの局所性の最適化にかなり適しています。これらのプロパティにより、これまでのところPATRICIAが私のお気に入りのアルゴリズムになっています...
私は、差し迫った関節炎の重症度を軽減するために、ここでこの説明を短くしますが、パトリシアについてもっと知りたい場合は、ドナルド・クヌースによる「コンピュータプログラミングの芸術、第3巻」などの本を参照できます。 、またはSedgewickによる「{your-favourite-language}のアルゴリズム、パート1〜4」のいずれか。
radix-tree
いうよりも少し迷惑だと思うのは私だけradix-trie
ですか?さらに、タグが付けられたかなりの数の質問があります。