トライと基数トライのデータ構造の違いは何ですか?


95

あるトライ基数トライデータ構造は同じもの?

それらが同じである場合、基数トライ(AKAパトリシアトライ)の意味は何ですか?


4
タグがとradix-treeいうよりも少し迷惑だと思うのは私だけradix-trieですか?さらに、タグが付けられたかなりの数の質問があります。
エラートリンギスト、2016年

@errantlinguist Wikipediaはradix trie記事にタイトルを付けRadix treeます。さらに、「基数木」という用語は、文献で広く使用されています。何かを呼び出すと、「接頭辞ツリー」が私にとってより意味をなすでしょう。結局のところ、これらはすべてツリーデータ構造です。
Amelio Vazquez-Reina

また、 「基数トライ(AKAパトリシアトライ)の意味は何ですか?」これは、基数ツリーとパトリシアツリーがまったく同じものであることを前提としていますが、そうではありません(たとえば、この回答を参照してください)。PATRICIAツリーは、PATRICIA アルゴリズムの実行から得られるツリーです(FYI PATRICIAは、「英数字でコード化された情報を取得するための実用的なアルゴリズム」の頭字語です)。結果の木はで基数木として理解することができradix = 2、あなたがいることを意味し、ツリーを横断検索して、log2(radix)=1一度に入力文字列のビットを。
Amelio Vazquez-Reina

回答:


118

基数ツリーは、トライの圧縮バージョンです。トライでは、各エッジに1文字を書き込みますが、パトリシアツリー(または基数ツリー)では、単語全体を格納します。

ここで、、、の単語helloがあるhatとしhaveます。それらをトライに格納するには、次のようになります。

    e - l - l - o
  /
h - a - t
      \
       v - e

そして、9つのノードが必要です。ノードに文字を配置しましたが、実際にはエッジにラベルが付けられています。

基数ツリーでは、次のようになります。

            *
           /
        (ello)
         /
* - h - * -(a) - * - (t) - *
                 \
                 (ve)
                   \
                    *

そして、必要なノードは5つだけです。上の図では、ノードはアスタリスクです。

したがって、全体として、基数ツリーは必要なメモリ少なくなりますが、実装は難しくなります。それ以外の場合、両方の使用例はほとんど同じです。


ありがとう... DS DSを研究するための優れたリソースを提供してくれませんか...それは大きな助けになります...
Aryak Sengupta

Trieを最初に実装したときに使用したのは、Wikipediaの記事だけだったと思います。完璧だと言っているわけではありませんが、それで十分です。
Ivaylo Strandjev 2013

1
TRIEでの検索はRadixツリーよりも速いと言えますか?TRIEでは、次の文字を検索したい場合は、現在のノードの子配列のi番目のインデックスを確認する必要がありますが、基数ツリーでは、すべての子ノードを順番に検索する必要があります。実装コードを
試行

4
実際、基数ツリーでは、同じ文字で始まるエッジを1つだけにすることができるため、同じ定数インデックスを使用できます。
Ivaylo Strandjev 2013

1
@Trying Algorithmically RadixはTRIEよりも高速です。そのため、圧縮を行う価値があります。ロードするノードが少なく、スペースが少ない方が一般に優れています。ただし、実装の品質はさまざまです。
Glenn Teitelbaum

68

私の質問は、トライのデータ構造と基数トライが同じものであるかどうかです。

つまり、いいえ。カテゴリ基数トライは、特定のカテゴリの説明トライを、それは、すべての試行が基数試行であることを意味するものではありません。

それらが同じでない場合、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.position4のa を使用してroot["smiles"[4]]、にアクセスしますroot['e']。これをという変数に格納しますcurrentcurrent.position差の位置である、5 "smiled"及び"smiles"ので、次のアクセスがされますroot["smiles"[5]]。これでsmiles_item、および文字列の終わりに到達します。検索が終了し、アイテムが取得されました。ノードアクセスは8回ではなく3回です。


パトリシアトライとは何ですか?

PATRICIAトライは、基数トライのバリアントでありnnアイテムの格納に使用されるノードのみが存在する必要があります。上記の我々の粗実証基数トライ擬似コードでは、合計で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」のいずれか。


「基数」という用語の重要性を理解するのに役立ちますか?自然な方法で、複数のシンボル/エッジを1つのエッジに合体させることで、TRIEをコンパクトなTRIEに変えようとする方法を理解しています。ただし、圧縮されていないTRIE(単純にTRIE)をRadix TRIEと呼ぶことができない理由を理解できません。
KGhatak

@ Seb- 基数ツリーのポストstackoverflow.com/questions/40087385/…へのフィードバックに本当に感謝します。前売のThnks。
KGhatak

@BuckCherryできるようになりたいのですが、私のコンピュータが盗まれたので、適切な対応に努力を払うことができなかったことを認識してください。
2016年

18

TRIE:
検索キー全体を既存のすべてのキーと比較する(ハッシュスキームなど)代わりに、検索キーの各文字を比較する検索スキームを使用できます。「 -このアイデアに続いて、我々は、既存の3つのキーがあり、構造(下に示すように)を構築することができお父さん」、「DAB」、および」タクシーを」。

         [root]
     ...// | \\...
           |  \
           c   d
           |    \
          [*]    [*]
      ...//|\.  ./|\\...        Fig-I
        a       a
       /       /
     [*]      [*]
 ...//|\..  ../|\\...
    /        /   \
   B        b     d
  /        /       \
 []       []       []

(cab)   (dab)     (dad)

これは基本的に、[*]で表される内部ノードと[]で表されるリーフノードを持つM-aryツリーです。この構造は、トライと呼ばれます。各ノードでの分岐の決定は、アルファベットの一意の記号の数、たとえばRに等しく保つことができます。小文字の英語のアルファベットの場合、az、R = 26、拡張ASCIIアルファベットの場合はR = 256、2進数/文字列の場合はR = 2。

コンパクトトライは:
典型的には、ノードトライはサイズ= Rを有するアレイを使用し、各ノードが少ないエッジを有する場合、したがってメモリの浪費を引き起こします。メモリの問題を回避するために、さまざまな提案がなされました。これらのバリエーションに基づいて、トライは「コンパクトトライ」および「圧縮トライ」とも呼ばれます。一貫した命名法はまれですが、ノードに単一のエッジがある場合、すべてのエッジをグループ化することにより、コンパクトトライの最も一般的なバージョンが形成されます。この概念を使用すると、キー(dad)、「dab」、および「cab」を持つ上記(図I)のトライは、以下の形式をとることができます。

         [root]
     ...// | \\...
           |  \
          cab  da
           |    \
          [ ]   [*]                Fig-II
               ./|\\...
                 |  \
                 b   d
                 |    \
                []    []

「c」、「a」、および「b」のそれぞれは、対応する親ノードの唯一のエッジであるため、単一のエッジ「cab」に統合されていることに注意してください。同様に、「d」と「a」は「da」というラベルの付いた単一のエッジにマージされます。

基数トライ:基数
という用語は、数学では、数値システムの基数を意味し、基本的に、そのシステムで任意の数値を表すために必要な一意の記号の数を示します。たとえば、10進法は基数10、2進法は基数2です。同様の概念を使用して、基礎となる表現システムの一意の記号の数によってデータ構造またはアルゴリズムを特徴付けることに関心がある場合は、概念に「基数」という用語でタグを付けます。たとえば、特定のソートアルゴリズムの「基数ソート」。同じロジック行で、トライのすべてのバリアント特性(深さ、メモリの必要性、検索ミス/ヒットの実行時間など)は、基になるアルファベットの基数に依存するため、基数を「トライ」と呼ぶ場合があります。たとえば、アルファベットa〜zを使用する場合、圧縮されていないトライと圧縮されたトライは、基数26 トライと呼ぶことができます。2つのシンボルのみ(従来は「0」と「1」)を使用するトライは、基数2のトライと呼ばれます。しかし、どういうわけか、多くの文献では、「基数トライ」という用語の使用は、コンパクト化されたトライだけに限定されていました。

パトリシアツリー/トリーの前奏曲:
キーとしての文字列でさえ、バイナリアルファベットを使用して表現できることに気付くのは興味深いことです。我々はASCIIエンコーディングを前提とした場合、キー「お父さん」はシーケンス内の各文字のバイナリ表現を書き込むことにより、バイナリ形式で記述することができ、「と言う01100100 01100001 01100100「D」のバイナリ形式を書き込むことで」、「」、および順次「d」。この概念を使用して、トライ(基数2)を形成できます。以下では、この概念を、「a」、「b」、「c」、および「d」の文字がASCIIではなく小さいアルファベットからのものであるという単純な仮定を使用して示します。

図IIIの注:先に述べたように、描写を簡単にするために、4つの文字{a、b、c、d}のみのアルファベットを想定し、対応するバイナリ表現が「00」、「01」、「10」、それぞれ「11」。これにより、文字列キー「dad」、「dab」、「cab」はそれぞれ「110011」、「110001」、「100001」になります。これのトライは、以下の図IIIに示すとおりです(ビットは、文字列が左から右に読み取られるように、左から右に読み取られます)。

          [root]
             \1               
              \
              [*]
             0/ \1               
             /   \
           [*]   [*]         
           0/     /               
           /     /0
         [*]    [*]      
        0/      /               
        /      /0
      [*]    [*]
     0/     0/ \1                Fig-III
     /      /   \
    [*]   [*]   [*]
     \1     \1    \1
      \      \     \
      []     []    []
    (cab)   (dab) (dad)

PATRICIA トライ /ツリー:
上記のバイナリトライ(図III)をシングルエッジ圧縮を使用して圧縮すると、ノードは上記のノードよりもはるかに少なくなりますが、ノードは3を超えます(キーの数) 。 Donald R. Morrisonは(1968年に)バイナリトライを使用してN個のノードのみを使用してN個のキーを表現する革新的な方法を発見し、このデータ構造をPATRICIAと名付けました。彼のトライ構造は本質的に単一のエッジ(一方向の分岐)を取り除きました。そうすることで、彼はまた、2種類のノード、つまり、内部ノード(キーを示さない)とリーフノード(キーを示す)の概念を取り除きました。上記で説明した圧縮ロジックとは異なり、彼のトライは異なる概念を使用しており、各ノードには、分岐の決定を行うためにスキップするキーのビット数が含まれています。彼のパトリシアトライのもう1つの特徴は、キーを格納しないことです。つまり、このようなデータ構造は、特定のプレフィックス一致するすべてのキーをリストするなどの質問に答えるのに適していませんが、キーが存在するかどうかを見つけるのに適しています。トライではない。それにもかかわらず、パトリシアツリーまたはパトリシアトライという用語は、コンパクトトライ[NIST]を示すため、または基数2を持つ基数トライ[微妙に示されるようにWIKIの方法]など。

基数トライではないかもしれないトライ:
3分探索トライ(3分探索ツリー別名)は、多くの場合と略記TSTは(によって提案されたデータ構造であるJ.ベントレー及びR. Sedgewick三方分岐を有するトライに非常に似ています)。このようなツリーの場合、各ノードには特徴的なアルファベット「x」があるため、キーの文字が「x」より小さいか、等しいか、大きいかによって分岐の決定が駆動されます。この固定3方向分岐機能により、特にR(基数)がUnicodeアルファベットのように非常に大きい場合、トライのメモリ効率の良い代替手段が提供されます。興味深いことに、(R-way)トライとは異なり、TSTにはRの影響を受けない特性があります。たとえば、TSTの検索ミスはln(N)です。R-way TrieのログR(N)とは対照的です。R-way トライとは異なり、TSTのメモリ要件はR の関数でもありません。したがって、TSTを基数トライと呼ぶことに注意する必要があります。個人的には、その基数のアルファベットの基数Rの影響を受ける特性はない(私が知る限り)ので、これを基数トライと呼ぶべきではないと思います。


2
Morrison、Sedgewick、KnuthによるPATRICIAを実装した人として、ここで説明したアルゴリズム(私も私の回答で説明しようとしました)、指定されたものと一致するすべてのキーをリストするなどの質問に答えるのに非常に適しています。接頭辞。PS誰かがボールに乗っているのを見るのは素晴らしいです:その他の質問:)私はその説明が好きです。
自閉症の

「「指定されたプレフィックスに一致するすべてのキーを一覧表示するなどの質問に答えるには適していない」と真剣に考えてください。
Pacerier

@Pacerier確かに!従来のPATRICIAは整数を格納します。これは配列のインデックスとして使用できます。配列に文字列を入れます。トライに、文字列の0ベースの配列インデックスを入れます。検索と比較とビット抽出関数が整数ではなく整数に対応する文字列に作用するようにし、挿入関数が他のものに基づいている場合(そうでなければならないが、そこには多くの繰り返しロジックがあるため)、そして順調です。integeruintptr_tとして使用することもできます。その型は通常、存在することが期待されている(必須ではありません)ようです。
自閉症の

あなたは、「多くの文献は、圧縮されたトライのためだけに「Radix Trie」という用語の使用を制限した」と述べています。実は、ウィキペディア以外の参考文献は見つかりません。他に何か見つけましたか?
wds

@ wds-私がこれを書いたときに私が参照したリソースが何であるか私は本当に覚えていないので、あなたは正しいかもしれません。迅速なグーグルでは、私は次のようにリンクを取得mathcs.emory.edu/~cheung/Courses/323/Syllabus/Text/trie02.htmlまたはtutorialsdiary.com/radix-trie-patricia-trie-or-compressed-trie本質的にポイントか(おそらく)wikiから派生/影響を受けています。他の信頼できる/学術的なリソースを見つけたら、ここに投稿します。
KGhatak
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.