【问题标题】:Print all paths from root to leaf in a Binary tree打印二叉树中从根到叶的所有路径
【发布时间】:2013-09-17 15:46:01
【问题描述】:

这是我编写的用于打印二叉树从根到叶的所有路径的代码:

public static void printRootToLeaf(Node1 root, List<Integer> list) {
    if(root == null) {
        return;
    }

    list.add(root.data);

    if(root.left == null && root.right == null) {
        System.out.println(list);
        return;
    }

        printRootToLeaf(root.left, list);
        printRootToLeaf(root.right, list);

}

我在 main 中这样调用这个方法:

public static void main(String[] args) {

    Node1 root = new Node1(1);
    Node1 two = new Node1(2);
    Node1 three = new Node1(3);
    Node1 four = new Node1(4);
    Node1 five = new Node1(5);
    Node1 six = new Node1(6);
    Node1 seven = new Node1(7);
    Node1 eight = new Node1(8);

    root.left = two;
    root.right = three;
    two.left = four;
    two.right = five;
    three.left = six;
    three.right = seven;
    five.left = eight;

    printRootToLeaf(root, new ArrayList<Integer>());

}

我得到了结果:

[1, 2, 4]
[1, 2, 4, 5, 8]
[1, 2, 4, 5, 8, 3, 6]
[1, 2, 4, 5, 8, 3, 6, 7]

在我期待的时候:

[1, 2, 4]
[1, 2, 5, 8]
[1, 3, 6]
[1, 3, 7]

我应该解决什么问题才能完成这项工作?我知道这类似于this,但我无法遵循该答案。谢谢。

【问题讨论】:

  • 每次调用printRootToLeaf 时,都会向list 添加一个节点。因此,每次打印 list 时,它的大小都会增加也就不足为奇了。

标签: java algorithm binary-tree tree-traversal


【解决方案1】:

问题是你没有删除元素,所以你沿着树的一侧向下走,填满你的列表,然后你向下走另一侧,旧元素仍然存在。

删除元素的未经测试的代码:

public static void printRootToLeaf(Node1 root, List<Integer> list) {
    if(root == null) {
        return;
    }

    list.add(root.data);

    if(root.left == null && root.right == null) {
        System.out.println(list);
        // cast so we don't remove by index (would happen if 'data' is an int)
        list.remove((Integer)root.data);
        return;
    }

    printRootToLeaf(root.left, list);
    printRootToLeaf(root.right, list);
    // cast so we don't remove by index  (would happen if 'data' is an int)
    list.remove((Integer)root.data);
}

remove(Object) 不是特别有效,使用LinkedList 然后removeLast() 可能是个好主意。

【讨论】:

    【解决方案2】:

    这是一个更简单的例子。

    Node1 root = new Node1(1);
    root.left = new Node(2);
    root.right = new Node(3);
    

    有了预期的结果

    [1,2]
    [1,3]
    

    以及实际结果

    [1,2]
    [1,2,3]
    

    当您第一次调用 printRootToLeaf 时,List 为空。你给它加1,然后在左边的分支上调用printRootToLeaf。在该调用中,您将 2 添加到列表中,并打印 [1,2]。然后您返回第一个调用,但 2 仍在列表中! 然后您在右侧分支上调用 printRootToLeaf。在该调用中,您将 3 添加到列表中,并打印 [1,2,3]

    在沿左分支递归时对列表所做的更改不应传播到沿右分支向下传递的列表。解决此问题的最简单方法是每次都复制列表:

    printRootToLeaf(root.left, copy(list));
    printRootToLeaf(root.right, copy(list));
    

    复制列表的实际方法会因您使用的语言而异。

    【讨论】:

    • 它是 Java,copy(list) => new ArrayList&lt;Integer&gt;(list)
    • 附带说明,在每一步复制列表并不是特别有效,在返回时删除添加的元素会更好。
    【解决方案3】:

    这是一个 C# 实现。您需要创建一个新列表并将现有路径放在那里。

        public static void PrintRoot2Leaves(Node root, List<int> path)
        {
            if (root == null) { return; }
            path.Add(root.Value);
            if (root.Left == null && root.Right == null)
            {
                Console.WriteLine(string.Join(",", path));
                return;
            }
            else {
                PrintRoot2Leaves(root.Left, new List<int>(path));
                PrintRoot2Leaves(root.Right, new List<int>(path));
            }
        }
    

    【讨论】:

      【解决方案4】:

      如果你有父节点的引用,下面的代码可以打印路径:

      public void printPaths(Node n) {
          if(n != null) {
              if(n.left == null && n.right == null) { // found a leaf node, go up the tree
                  StringBuilder sb = new StringBuilder();
                  sb.append(" ").append(n);
                  Node p = n.parent;
                  while(p != null) {
                      sb.insert(0, " ").insert(1,p);
                      p = p.parent;
                  }
                  System.out.println(sb);
              }
              printPaths(n.left);
              printPaths(n.right);
          }
      }
      

      【讨论】:

        【解决方案5】:

        这里的问题是您是如何获得解决方案的,而不是您是否获得了解决方案。性能是这里的关键。 首先创建一个树对象..

        class Node {
        
        public Node left;
        public Node right;
        public Character val;
        
        public Node(char val) {
            this.val = val;
        }   
        

        获取列表中的所有路径..

        public List<LinkedList<Node>> printPath(Node root) {
        
            if (root == null) return new ArrayList<LinkedList<Node>>();
        
            List<LinkedList<Node>> left = printPath(root.left);
            List<LinkedList<Node>> right = printPath(root.right);
        
            left.addAll(right);
        
            for (LinkedList<Node> lst : left) {
                lst.addFirst(root);
            }
            if(left.size()==0){
                LinkedList<Node> lst= new LinkedList<Node>();
                lst.add(root);
                left.add(lst);
            }
            return left;
        
        }
        

        现在打印所有路径..

          Node root = new Node('a');
            System.out.println(root.val);
            root.left = new Node('b');
            root.left.left = new Node('c');
            root.left.right = new Node('d');
            root.right = new Node('e');
            root.right.left = new Node('f');
            root.right.right = new Node('g');
            root.right.right.left = new Node('h');
        
            List<LinkedList<Node>> allPaths = wc.printPath(root);
        
            for (LinkedList<Node> lst : allPaths) {
                for (Node node : lst)
                    System.out.print(node.val==null ? "-" : node.val);
                System.out.println();
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-08-29
          • 2021-09-29
          • 1970-01-01
          • 1970-01-01
          • 2018-03-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多