二分木に深さ優先の後順でアクセスし、オフセットを使用して、開始ノードに対して左/右にどれだけ移動したかを追跡できます。左に移動するたびにオフセットが減少し、右に移動するたびにオフセットが増加します。訪問手順が のオフセットで呼び出された場合、訪問0
されているノードが開始ノードと同じオフセットを持っている (つまり、同じ列にある) ことを意味するため、その値を追加する必要があります。
擬似コード:
procedure visit (node n, int offset) {
sumleft = 0
sumright = 0
if (n.left != null)
sumleft = visit(n.left, offset - 1)
if (n.right != null)
sumright = visit(n.right, offset + 1)
if (offset == 0)
return n.value + sumleft + sumright
else
return sumleft + sumright;
}
たとえば、
visit(A, 0)
次の呼び出しが表示されます。
visit(A, 0) -> E.value + F.value + A.value
visit(B, -1) -> E.value
visit(D, -2) -> 0
visit(H, -3) -> 0
visit(I, +2) -> 0
visit(E, 0) -> E.value
visit(C, +1) -> F.value
visit(F, 0) -> F.value
visit(G, +1) -> 0
node から始まる別の例B
:
visit(B, 0)
visit(D, -1)
visit(H, -2)
visit(I, 0) -> here we return I.value
visit(E, +1)
再帰が と の最初の呼び出しvisit(B, 0)
に戻るsumleft = I.value
とsumright = 0
、期待どおり最終的な結果が返さB.value + I.value
れます。
開始ノードをルートとするツリーのすべてのノードに一度アクセスするため、O(n) の複雑さ。
上記のアルゴリズムについて考えた後、次のようなより複雑なツリーを検討すると明らかになる制限があることに気付きました。

この場合visit(B, 0)
でも が返されますが、 も同じ列にあるB.value + I.value
ため、これは期待される結果ではありません。N
次のアルゴリズムは、この問題に対処する必要があります。
procedure visit(node n, int c, int t) {
sumleft = 0;
sumright = 0;
if (n.left != null)
sumleft = visit(n.left, c - 1, t)
if (n.right != null)
sumright = visit(n.right, c + 1, t)
if (c == t)
return n.value + sumleft + sumright;
else
return sumleft + sumright;
}
考え方は基本的に同じですがc
、現在の列を指定するパラメーターt
と、ターゲット列を指定するパラメーターがあります。列の要素の合計が必要な場合は、B
を呼び出すことができますvisit(A, 0, -1)
。つまり、常に列 0 にあるノード (ルートのツリー) から訪問を開始しA
、ターゲットは列 -1 です。次の結果が得られます。

したがってvisit(A, 0, -1) = B + I + N
、予想どおり。
複雑さは常に O(n) です。n はツリー内のノードの数です。深さ優先の後順でツリー全体を調べ、各ノードを 1 回だけ処理するためです。
すべての列の合計を計算したい場合は、次のアルゴリズムを使用できます
procedure visit(node n, int c) {
if (n.left != null)
S{c} += n.value;
visit(n.left, c - 1)
visit(n.right, c + 1)
}
と呼び出し once visit(A, 0)
、ここA
で はルートノードです。S{...}
アルゴリズムには、キーが列番号 (...、-2、-1、0、1、2、...) であり、値 (アルゴリズムの最後) が合計であるマップがあることに注意してください。その列のノードの値 (S{1}
は列 1 のノードの合計になります)。インデックスに注意を払えば、マップの代わりに配列を使用することもできます (配列には負のインデックスがありません)。ツリー全体を 1 回だけトラバースするため、アルゴリズムは O(n) のままです。ただし、この場合、すべての列 (マップまたは配列) の合計を格納するために追加のスペースが必要です。私が間違っていなければ、高さの二分木にh
は2*h + 1
列があります。