繁体   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