詳解 LOUDS (5) 木構造の復元


今回は、LOUDS のデータから木構造が復元できることを示します。

次のような手順により実現できます。


まず、木構造の深さ 0 に、根(0番ノード)がひとつある状態から始め、0番ノードを「今見ている親ノード」、LOUDS データの最初のビットを「今見ているビット」とした上で、次の手順をビット列の終わりまで行います。

今見ているビットが "1" であれば:
  「今見ている親ノード」に対して子ノードを増やす。番号は、前に増やした子ノードの番号に 1 を足したもの。
今見ているビットが "0" であれば:
  「今見ている親ノード」の番号に 1 を足したものを、新しい「今見ている親ノード」とする。

次のビットに移る。

とても単純な手順なのですが、これだけではイメージがわかないかと思います。

実際のデータを元にしてやってみることにします。できれば、紙に書いてやってみてください。


最初に挙げた大きな木構造に対する LOUDS のビット列は次のようなものでした。ここでは、ビット列のみに注目します。

これに対して、上記の手順を適用してみます。

まず、最初に 0番ノードを最初に置き、それを「今見ている親ノード」とします。「今見ている親ノード」は、太線で、赤い矢印をつけています。

また、「今見ているビット」は左端のビットになります。「今見ているビット」は、薄く色をつけたところです。

今見ているビットは "1" なので、「今見ている親ノード」(0番ノード)に子ノードを増やします。番号は、0 の次で 1 とします。

「今見ているビット」をひとつ右に移します。

今見ているビットが "0" なので、「今見ている親ノード」を、0番ノードから 1番ノードに移します。

次のビットに移ります。

今見ているビットは "1" なので、「今見ている親ノード」(1番ノード)に子ノードを増やします。番号は、1 の次で 2 とします。

次のビットに移ります。

今見ているビットは "1" なので、「今見ている親ノード」(1番ノード)に子ノードを増やします。番号は、2 の次で 3 とします。

次のビットに移ります。

今見ているビットは "1" なので、「今見ている親ノード」(1番ノード)に子ノードを増やします。番号は、3 の次で 4 とします。

次のビットに移ります。

今見ているビットが "0" なので、「今見ている親ノード」を、1番ノードから 2番ノードに移します。

次のビットに移ります。

今見ているビットは "1" なので、「今見ている親ノード」(2番ノード)に子ノードを増やします。番号は、4 の次で 5 とします。

次のビットに移ります。

今見ているビットが "0" なので、「今見ている親ノード」を、2番ノードから 3番ノードに移します。

次のビットに移ります。

今見ているビットが "0" なので、「今見ている親ノード」を、3番ノードから 4番ノードに移します。

以降は省略しますが、このような手順で木構造が復元できることがわかると思います。



この手順の中では、あえて「親」と「子」の行には触れませんでした。

改めて、「親」と「子」の行の意味について見てみます。

例えば、上の手順の中で、「今注目しているビット」が次のようになっている状態に戻ってみます。

「今見ている親ノード」(1番ノード)に、3番ノードという子ノードを増やすところです。

ここで、表で「今注目しているビット」の上下を見て下さい。

上(「親」)の行は "1"、下(「子」)の行は "3" となっています。

これは、このビットが「1番ノードを親とする、3番ノード」を表していることを意味します。

そういうわけで、ここでは 1番ノードを親として、それに 3番ノードを子として追加することになるわけです。



今回のまとめです。
  • LOUDS のビット列から、元の木構造を復元することができる。

実際に LOUDS を利用する時には、木構造を別の場所に展開することなく、データそのままの形で、「親ノードから子ノードを列挙する」「子ノードから親ノードをたどる」といった操作を行えます。その詳細については、次回以降解説します。



今回の問題です。

次のビット列から、格納された木構造を復元してみてください。



前回の答えです。

"1" のビットが、左から順番に、1, 2, 3... というノード番号に対応しています。