簡體   English   中英

打印二叉樹的所有可能直徑?

[英]Print all possible diameters of Binary Tree?

我知道如何計算樹的直徑 ,但是我想打印所有可能的樹直徑。 以下面的例子為例: -

        1
       / \
      2   3
     /   / \
    4   5   6

以上樹木的所有可能直徑為: -

First:  4 2 1 3 5
Second: 4 2 1 3 6

任何有關方法的幫助都會非常有用。

我假設您是指從一片葉子到另一片葉子的最大長度的所有可能路徑?

遞歸可能是最好的選擇-使用偽代碼,例如:

path(startNode, endNode) {
  if startNode = endNode return;
  for each possible next node n {
    add n to your path;
    path(n, endNode);
  }
}

您可以為每對葉子調用此方法,然后丟棄任何非最大長度的路徑,或者選擇以一種更聰明的方式調用哪個葉子,我將留給您

如何在圖中完成:

  1. 從任何節點n運行BFS以找到最遠的節點(來自該節點)n'
  2. 從節點n'到他最遠的節點n''運行BFS
  3. 從n'到n''的路徑是樹的直徑

所以,看一棵樹(可以展開成圖表):

直徑路徑從左子樹中最低級別上的任何葉子到右子樹中最低級別上的任何葉子。

現在,由於您無法神奇地知道哪個2個節點是直徑的末端節點,並且您只有父子鏈接,因此上述算法本身就行不通。 但是,您可以使用類比來構建一個適用於樹而不是圖的類。

好的,這是您可以使用的一些快速代碼(它可能不是最佳方法,但是可以使用)

public class BinarySearchTree {
    ...

    public Iterable<T> diameter() {
        if (this.root == null) {
            return null;
        }

        Deque<T> diameterLeftPart = new ArrayDeque<T>();
        Deque<T> diameterRightPart = new ArrayDeque<T>();

        diameter(this.root.left, diameterLeftPart);
        diameter(this.root.right, diameterRightPart);

        Deque<T> diameter = new ArrayDeque<T>();

        for (Iterator<T> it = diameterLeftPart.iterator(); it.hasNext();) {
            diameter.offerLast(it.next());
        }

        diameter.offerLast(this.root.item);

        for (Iterator<T> it = diameterRightPart.descendingIterator(); it.hasNext();) {
            diameter.offerLast(it.next());
        }

        return diameter;
    }

    private void diameter(Node node, Deque<T> diameter) {
        if (node == null)  {
            return;
        }

        Deque<T> leftPart = new ArrayDeque<T>();
        Deque<T> rightPart = new ArrayDeque<T>();

        diameter(node.left, leftPart);
        diameter(node.right, rightPart);

        if (leftPart.size() > rightPart.size()) {
            diameter.addAll(leftPart);
        } else {
            diameter.addAll(rightPart);
        }

        diameter.offerLast(node.item);
    }

    ...
}

和跑步者班:

public class TreeDiameter {
    public static void main(String[] args) {
        Tree<Integer> tree = new BinarySearchTree<Integer>();
        tree.add(5);
        tree.add(2);
        tree.add(8);
        tree.add(1);
        tree.add(3);
        tree.add(7);
        tree.add(9);
        tree.add(4);
        tree.add(6);

        for (Integer diameterNode : tree.diameter()) {
            System.out.print(diameterNode + " ");
        }
    }
}

使用以下輸出:

4 3 2 5 8 7 6 

快速解釋:

我們知道,根是直徑路徑的組成部分。 因此,我們希望獲得左子樹中最長的路徑和右子樹中的最長路徑。
膠合在一起,他們創造了一個直徑。

使用遞歸調用diameter(node.left, leftPart)diameter(node.right, rightPart)leftPartrightPart包含left和right子樹中的最長路徑。

簡單地比較它們的尺寸就可以指示我們將用於構建樹上一層的直徑。

所以,總結一下:
遞歸首先一直向下到樹,然后返回該子樹中的最長路徑,然后將其向上傳遞到其父級,一直到根。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM