这是我编写的用于打印从根到叶子的二叉树的所有路径的代码:
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);
}
我这样称呼这个方法:
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类似,但我无法回答这个问题。感谢。
答案 0 :(得分:3)
问题在于你没有删除元素,所以你走到树的一边,填满你的列表,然后你往下走,旧的元素仍在那里。
删除元素的未经测试的代码:
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()
可能是一个好主意。
答案 1 :(得分:1)
这是一个更简单的例子。
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));
复制列表的实际方法取决于您使用的语言。
答案 2 :(得分:1)
这是一个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));
}
}
答案 3 :(得分:0)
如果您有对父节点的引用,则以下代码可以打印路径:
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);
}
}
答案 4 :(得分:0)
这里的问题是你是如何得到解决方案而不是你得到解决方案的。性能是关键。 首先创建一个树对象..
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();
}