web-dev-qa-db-ja.com

バイナリツリーの効率的なアレイストレージ

バイナリツリーのノードをファイルに書き込む必要があります。バイナリツリーを書く最もスペース効率の良い方法は何ですか。親をiに配置し、その子を2i2i+1に配列形式で格納できます。しかし、これはスパースな二分木の場合に多くのスペースを浪費します。

32
Sundararajan S

私が好む1つの方法は、プレオーダートラバーサルを格納することですが、そこに「null」ノードを含めることもできます。 「null」ノードを格納すると、ツリーの順序も格納する必要がなくなります。

この方法のいくつかの利点

  • ほとんどの実際的なケースでは、pre/post + inorderメソッドよりも優れたストレージを実行できます。
  • シリアライゼーションはたった1つのトラバーサルをとります
  • 逆シリアル化は1つのパスで実行できます。
  • インオーダートラバーサルは、ツリーを構築せずに1つのパスで取得できます。これは、状況がそれを必要とする場合に役立ちます。

たとえば、64ビット整数のバイナリツリーがあるとすると、各ノードの後に​​次のビットがnullノードかどうかを示す追加のビットを格納できます(最初のノードは常にルートです)。ノードがnullの場合、1ビットで表すことができます。

したがって、n個のノードがある場合、スペースの使用量は8nバイト+ n-1標識ビット+ nullノードのn + 1ビット= 66 * nビットになります。

Pre/post + inorderでは、16nバイト= 128 * nビットを使用することになります。

したがって、このpre/post + inorderメソッドよりも62 * nビットのスペースを節約できます。

木を考える

       100
      /   \
     /     \
    /       \
   10       200
  / \       /  \
 .   .     150  300
          / \    / \
         .   .   .  .

どこ '。' nullノードです。

100 10 . . 200 150 . . 300 . .としてシリアル化します

これで、各(サブツリーを含む)「nullを使用したプレオーダートラバーサル」には、nullノードの数=ノードの数+ 1というプロパティがあります。

これにより、最初のノードがツリーのルートであるため、シリアル化されたバージョンを1回のパスで指定してツリーを作成できます。後続のノードは、左側のサブツリーの後に右側が続き、次のように表示できます。

100 (10 . .) (200 (150 . .) (300 . .))

インオーダートラバーサルを作成するには、ノードが表示されたときにスタックとプッシュを使用し、nullが表示されたときに(リストに)ポップします。結果のリストは、順序のトラバーサルです(これの詳細な説明はここにあります C++/C/Java:Anagrams-元の文字列からターゲットへ; )。

39
Aryabhatta

XMLについて考えてください。これは一種のツリーのシリアル化です。例えば:

<node id="1">
    <node id="2">                                   1
    </node>                                       /   \
    <node id="3">                                2     3
        <node id="4">                                 / \
        </node>                                      4   5
        <node id="5">
        </node>
    </node>
</node>

では、なぜスペースとタグなのか?私たちはそれらを段階的に省略できます:

<1>
   <2></>
   <3>
     <4></>
     <5></>
   </>
</>

スペースを削除します:<1><2></2><3><4></><5></></></>

山かっこを削除します:12/34/5///

ここで問題は、ノードに空の左サブツリーと空でない右サブツリーがある場合はどうなりますか?次に、別の特殊文字「#」を使用して、空の左サブツリーを表すことができます。

例えば:

    1
  /   \
      2
     /  \
    3

このツリーは次のようにシリアル化できます:1#23///

5
Ray

(ほぼ)完全なツリーがある場合、2i、2i + 1(バイナリヒープ)メソッドは確かに最良の方法です。

それ以外の場合、ParentId(親インデックス)を各ノードに格納することを回避できません。

4
Henk Holterman

in-orderおよびpre/post-orderファイル内のバイナリツリーの走査を行い、これらの走査からツリーを再構築します。

1
codaddict