次の木を想像してみてください。
A
/ \
B C
/ \ \
D E F
たとえば、FがAの子孫であるかどうかを照会する方法を探しています(注:FはAの直接の子孫である必要はありません)。これは、この特定の場合に当てはまります。より大きな潜在的な子孫ノードプールに対してテストする必要があるのは、限られた量の潜在的な親ノードのみです。
ノードが潜在的な親プール内のノードの子孫であるかどうかをテストする場合、すべての潜在的な親ノードに対してテストする必要があります。
これが思いついたものです:
マルチウェイツリーをトライに変換します。つまり、上記のツリーのすべてのノードに次のプレフィックスを割り当てます。
A = 1 B = 11 C = 12 D = 111 E = 112 F = 121
次に、可能なすべてのプレフィックスサイズのビット配列を予約し、テスト対象の親ノードを追加します。つまり、Cが潜在的な親ノードプールに追加されている場合は、次のようにします。
1 2 3 <- Prefix length *[1] [1] ... [2] *[2] ... [3] [3] ... [4] [4] ... ... ...
ノードが潜在的な親ノードの子孫であるかどうかをテストするときは、そのtrieプレフィックスを取得し、最初の「プレフィックス配列」(上記を参照)の最初の文字を検索し、存在する場合は、2番目の「プレフィックス」の2番目のプレフィックス文字を検索します配列」など、つまりFをテストすると次のようになります。
F = 1 2 1 *[1] [1] ... [2] *[2] ... [3] [3] ... [4] [4] ... ... ...
そうです、FはCの子孫です。
このテストは最悪の場合のO(n)のようです。ここで、n =最大プレフィックス長=最大ツリーの深さです。したがって、最悪のケースは、ツリーを上ってノードを比較するという明白な方法とまったく同じです。ただし、テスト対象のノードがツリーの最下部近くにあり、潜在的な親ノードが最上部にある場合、これははるかに優れたパフォーマンスを発揮します。両方のアルゴリズムを組み合わせると、両方の最悪のシナリオが緩和されます。ただし、メモリのオーバーヘッドが問題になります。
それを行う別の方法はありますか?どんなポインタでも大歓迎です!