打印二叉树的所有可能直径?

时间:2015-02-12 13:05:11

标签: java data-structures binary-tree

我知道如何计算树的diameter,但我想打印树的所有可能直径。以下面的例子为例: -

        1
       / \
      2   3
     /   / \
    4   5   6

上述树中所有可能的直径为: -

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

任何有关方法的帮助都会非常有用。

2 个答案:

答案 0 :(得分:0)

我假设你指的是从一片叶子到另一片叶片的最大长度的所有可能路径?

递归可能是你最好的选择 - 伪代码如下:

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

你可以为每对叶子调用这个,然后抛弃任何非最大长度的路径,或者选择哪些叶子以更聪明的方式调用它,我会留给你

答案 1 :(得分:0)

如何在图表中完成:

  1. 从任何节点n运行BFS以找到最远的节点(来自该节点)n'
  2. 从节点n'运行BFS。到他最遥远的节点n'
  3. n'的路径到了''是树直径
  4. 所以,看一棵树(可以展开成图表):

    直径路径从左子树中最低级别的任何叶子到右子树中最低级别上的任何叶子。

    现在,既然你不会神奇地知道哪两个节点是直径的终点节点,并且你只有父对子链接,那么上述算法本身就不适用。但是,您可以使用类比来构建一个适用于树而不是图形的工具。

    好的,这里有一些你可以使用的快速代码(它可能不是最佳的,但它可以工作)

    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分别包含左侧和右侧子树中最长的路径。

    简单地比较它们的尺寸就可以指示我们将用于构建树上一层的直径。

    所以,总结一下:
    递归首先一直向下到树,并返回该子树中最长的路径,将其向上传递给它的父,一直到根。