web-dev-qa-db-ja.com

二分木の高さ

次のコードを検討してください。

public int heightOfBinaryTree(Node node)
{
    if (node == null)
    {
        return 0;
    }
    else
    {
        return 1 +
        Math.max(heightOfBinaryTree(node.left),
            heightOfBinaryTree(node.right));
    }
}

このコードの背後にある論理的な理由を知りたい。人々はどうやってそれを思いついたのですか?一部には帰納的証拠がありますか?

さらに、バイナリツリーのルートを引数としてBFSを実行して、バイナリツリーの高さを取得することを考えました。以前のアプローチは私のアプローチよりも優れていますか?

36
Programmer
if (node == null)
{
    return 0;
}

リーフノードの子はnullです。したがって、これは葉を通過すると、それ以上のノードがないことを意味しています。

リーフノードを通過していない場合、高さを計算する必要があり、このコードは再帰的に計算します。

return 1 +

現在のノードは、現在計算されているサブツリーの高さに1の高さを追加します。

    Math.max(heightOfBinaryTree(node.left),
        heightOfBinaryTree(node.right));

左のサブツリー(node.left)と右のサブツリー(node.right)の高さを再帰的に計算します。最大深度を計算しているため、これら2つの深度の最大値を取得します。

上記で、再帰関数が正しいことを示しました。したがって、親ノードで関数を呼び出すと、ツリー全体の深さが計算されます。

このドキュメント からのツリーの高さのグラフィカルな表現を次に示します。 hはツリーの高さ、hlhrはそれぞれ左と右のサブツリーの高さです。

さらに、バイナリツリーの高さを取得するための引数としてバイナリツリーのルートを使用してBFSを実行することを考えました。以前のアプローチは私のアプローチよりも優れていますか?

指定したコードは、DFSの形式です。ツリーの高さを見つけるためにすべてのノードを処理する必要があるため、BFSはO(N)メモリを使用し、DFSはO(logN)メモリ。また、BFSは、DFSが「組み込み」再帰スタックを利用する間にキューを必要とするため、コードがやや複雑です。

48
marcog

そのコードの背後にあるロジックは次のとおりです。

ノードには2つの子があるため、ツリーの高さは、左の子と右の子をルートとする木の高さの最大値になり、もちろん子へのウォークでは+1になります。

ご覧のとおり、上記の説明は再帰的であり、コードも再帰的です。

BFSも実行する必要がありますが、実装と空間/時間の両方の複雑さのため、やり過ぎです。

再帰関数は理解するのは難しいが、実装するのは非常にエレガントであるという発言があります。

4
Shamim Hafiz

木の高さは、そのルートから最も長い下向きのパスの長さです。この関数は、バイナリツリーのレベルをカウントする再帰的な方法です。ツリーを下るときにカウンターをインクリメントし、最大カウンター(最下位ノードのカウンター)を返します。

お役に立てば幸いです。

2
tiagovrtr

これは再帰的な関数です。木の高さは、1 +その最も高い枝の高さです。

BFSは幅の広い最初の検索ですか?効率にどのような違いがあるのか​​はわかりませんが、再帰関数のシンプルさが気に入っています。

0
Adrian Mouat