打印树的每个叶子路径而不递归
Posted
技术标签:
【中文标题】打印树的每个叶子路径而不递归【英文标题】:Print every leaf path of a tree without recursive 【发布时间】:2012-06-15 06:03:50 【问题描述】:如何在不使用递归的情况下打印树的每个叶子路径。
它是一棵树,不是二叉树
struct node
int data
std::vector<node*> children;
打印从根到叶子的所有路径,即下面是树
r:是根节点 d、m、n 是 r 的孩子 x,y,z 是 d 的孩子 m 没有孩子 o, p 是 n 的孩子 - - - - - - -根 ------d m n ---x y z o p结果应该是:
根-d-x 根-d-y 根-d-z 根-m root-n-o 根-n-p我尝试使用非递归方式但失败了。
【问题讨论】:
我相信您可以根据自己的情况调整非递归二叉树遍历。具有最小内存开销的最简单实现将在node
中有一个父节点指针。见nonRecursiveInOrderTraversal()。
【参考方案1】:
public static void printAllPathToLeafNonRecursive(Node root)
if (root == null)
return;
Queue<Object> q = new LinkedList<Object>();
q.add(root);
q.add(root.data + "");
while(!q.isEmpty())
Node head = (Node) q.poll();
String headPath = (String) q.poll();
if(head.isLeaf())
System.out.println(headPath);
continue;
if(head.left!=null)
String leftStr = headPath + "->" + head.left.data;
q.add(head.left);
q.add(leftStr);
if(head.right!=null)
String rightStr = headPath + "->" + head.right.data;
q.add(head.right);
q.add(rightStr);
【讨论】:
这不会也打印出路径上的一些节点吗? @CyberneticTwerkGuruOrc 不,它没有。查看它使用队列的方式。它也将字符串推送到队列中,因此它不会被路径节点之外的节点写入。它被适当地轮询和附加:) @smihael:对于超过 2 个孩子的树,可以修改上述解决方案。不要插入 head.left 和 head.right,而是使用:for(int i = 0; i " + head.children[i].data ; q.add(head.children[i]); q.add(si); 有点晚了,但我想指出这真的很慢,因为它为每个节点(不仅仅是叶子)复制一个字符串。如果 N 是 # 个节点,K 是 # 个叶子,通常的算法在 O(KN) 中运行,但在 O(N^2) 中运行,这对任意非二叉树有很大的不同【参考方案2】:这是一个纯粹基于使用堆栈的预排序迭代遍历的 Python 解决方案。打印路径和路径和。
class Stack(object): # just for reference
def __init__(self):
self.a = []
def push(self, b):
self.a.append(b)
def peek(self):
return self.a[-1]
def pop(self):
return self.a.pop()
def isEmpty(self):
return len(self.a) == 0
def show(self):
return self.a
def paths(troot): # you should create your own Tree and supply the root
current = troot
s = Stack()
s.push(current)
s.push(str(current.key))
s.push(current.key)
while not s.isEmpty():
pathsum = s.pop()
path = s.pop()
current = s.pop()
if not current.left and not current.right:
print 'path: %s, pathsum: %d' % (path, pathsum)
if current.right:
rightstr = path + "->" + str(current.right.key)
rightpathsum = pathsum * 10 + current.right.key
s.push(current.right)
s.push(rightstr)
s.push(rightpathsum)
if current.left:
leftstr = path + "->" + str(current.left.key)
leftpathsum = pathsum * 10 + current.left.key
s.push(current.left)
s.push(leftstr)
s.push(leftpathsum)
例如,对于以下树:
3
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
1 7
/ \ / \
/ \ / \
/ \ / \
/ \ / \
0 2 5 8
/ \ / \ / \ / \
/ \ / \ / \ / \
NUL NUL NUL NUL 4 6 NUL 9
输出将是:
>>> paths()
path: 3->1->0, pathsum: 310
path: 3->1->2, pathsum: 312
path: 3->7->5->4, pathsum: 3754
path: 3->7->5->6, pathsum: 3756
path: 3->7->8->9, pathsum: 3789
【讨论】:
【参考方案3】:策略很简单。向下,向右,然后向上。在每一个点上,您都知道下一步该去哪里。
保留一个向量,它是您在树中的当前位置。在根上启动它。然后在伪代码中:
while True:
if not a leaf:
current_place.push_back(0) // move down one
else:
print current path.
while can't move right:
if at root:
exit()
current_place.pop_back() //move up one
current_place[-1] += 1
这些操作将需要函数调用。但它们是带有循环的函数调用,而不是递归,所以它不是递归的。
【讨论】:
基本上,您需要使用显式堆栈操作来模拟递归函数的行为。 @Groo,没错。我考虑过使用队列,但这不会按要求的顺序排列。 这个算法(虽然缺少一些细节)是更好的选择。【参考方案4】:最后,它只是一个图表。有不同类型的图遍历。只需将 dfs 与堆栈一起使用,并打印您没有前边缘的节点。
【讨论】:
【参考方案5】:public static void RoottoPathPrint(BinaryTreeNode root)
Stack<Object> stack = new Stack<Object>();
if (root == null)
return;
stack.push(root.getData() + "");
stack.push(root);
while (!stack.isEmpty())
BinaryTreeNode temp = (BinaryTreeNode) stack.pop();
String path = (String) stack.pop();
if (temp.getRight() != null)
stack.push(path + temp.getRight().getData());
stack.push(temp.getRight());
if (temp.getLeft() != null)
stack.push(path + temp.getLeft().getData());
stack.push(temp.getLeft());
if (temp.getLeft() == null && temp.getRight() == null)
System.out.println(path);
我们的想法是在我们遍历树时跟踪单个堆栈中的路径和节点。对象堆栈负责这一点。 希望对您有所帮助!
【讨论】:
【参考方案6】:private void rootToLeaf(BSTNode root)
Stack<Map<BSTNode,ArrayList<Integer>>> tmpStack = new Stack<Map<BSTNode,ArrayList<Integer>>>();
Map<BSTNode,ArrayList<Integer>> tmpMap = new HashMap<BSTNode,ArrayList<Integer>>();
//List<Integer> tmp_arraylist = new ArrayList<Integer>();
ArrayList<Integer> tmpList = new ArrayList<Integer>();
tmpList.add(root.data);
tmpMap.put(root, tmpList);
tmpStack.push(tmpMap);
while(!tmpStack.isEmpty())
Map<BSTNode,ArrayList<Integer>> temp_map = tmpStack.pop();
for(BSTNode node : temp_map.keySet())
if(node.getLeft()==null && node.getRight()==null)
for(int i: temp_map.get(node))
System.out.print(i+" ");
System.out.println();
if(node.getRight()!=null)
ArrayList<Integer> tmp_List = new ArrayList<Integer>();
for(int i: temp_map.get(node))
tmp_List.add(i);
tmp_List.add(node.getRight().getData());
Map<BSTNode,ArrayList<Integer>> tmphashMap = new HashMap<BSTNode,ArrayList<Integer>>();
tmphashMap.put(node.getRight(), tmp_List);
tmpStack.push(tmphashMap);
if(node.getLeft()!=null)
ArrayList<Integer> tmp_List = new ArrayList<Integer>();
for(int i: temp_map.get(node))
tmp_List.add(i);
tmp_List.add(node.getLeft().getData());
Map<BSTNode,ArrayList<Integer>> tmphashMap = new HashMap<BSTNode,ArrayList<Integer>>();
tmphashMap.put(node.getLeft(), tmp_List);
tmpStack.push(tmphashMap);
【讨论】:
【参考方案7】:对于 n 叉树 - 基于 DFS 和 BFS 的路径,求和
100
/ / \ \
1 2 3 4
/ / / / / / \
10 11 12 13 14 40 41
/ \
400 401
public void traverseDFS(Node root)
Stack<Node> s = new Stack<Node>();
Stack<String> sPath = new Stack<>();
Stack<Integer> sSum = new Stack<>();
s.push(root); sPath.push(root.Id + ""); sSum.push(root.Id);
while (!s.isEmpty())
// Pop out
Node head = s.pop(); String headPath = sPath.pop(); Integer headSum = sSum.pop();
if(head.children == null || head.children.isEmpty()) //Leaf
System.out.println(headPath + "(" + headSum+")");
continue;
for(Node child : head.children)
String path = headPath + "->" + child.Id;
Integer sum = headSum + child.Id;
// Push on stack
s.push(child); sPath.push(path); sSum.push(sum);
public static void traverseBFS(Node root)
Queue<Node> q = new LinkedList<>();
Queue<String> qPath = new LinkedList<>();
Queue<Integer> qSum = new LinkedList<>();
q.add(root); qPath.add(root.Id + ""); qSum.add(root.Id);
while(!q.isEmpty())
// Poll the q
Node head = q.poll(); String headPath = qPath.poll(); Integer headSum = qSum.poll();
if(head.children == null || head.children.isEmpty()) //Leaf
System.out.println(headPath + "(" + headSum+")");
continue;
for(Node child : head.children)
String path = headPath + "->" + child.Id;
Integer sum = headSum + child.Id;
// Add to the q
q.add(child); qPath.add(path); qSum.add(sum);
class Node
int Id;
String Data;
Node Parent;
ArrayList<Node> children;
public Node(int id, String data)
Id = id;
Data = data;
输出
-----------Depth FS-------------
100->4->41(145)
100->4->40->401(545)
100->4->40->400(544)
100->3(103)
100->2(102)
100->1->14(115)
100->1->13(114)
100->1->12(113)
100->1->11(112)
100->1->10(111)
-----------BFS-------------
100->2(102)
100->3(103)
100->1->10(111)
100->1->11(112)
100->1->12(113)
100->1->13(114)
100->1->14(115)
100->4->41(145)
100->4->40->400(544)
100->4->40->401(545)
【讨论】:
【参考方案8】:public void allPathsToLeafNodesWithPreOrderDFS()
Stack<Node> stack = new Stack<> ();
stack.push (root);
List<Deque<Integer>> paths = new ArrayList<> ();
while (!stack.isEmpty ())
Node pop = stack.pop ();
System.out.print (" " + pop.data);
if (pop.isLeaf ())
Deque<Integer> path = new ArrayDeque<> ();
Node current = pop;
while (current != null)
path.add (current.data);
current = current.parent;
paths.add (path);
if (pop.right != null)
pop.right.parent = pop;
stack.push (pop.right);
if (pop.left != null)
pop.left.parent = pop;
stack.push (pop.left);
System.out.println ("paths = " + paths);
public void allPathsToLeafNodesWithInOrderDFS()
Stack<Node> stack = new Stack<> ();
List<Deque<Integer>> paths = new ArrayList<> ();
Node current = root;
while (!stack.isEmpty () || current != null)
if (current != null)
stack.push (current);
if (current.left != null) current.left.parent = current;
current = current.left;
else
Node pop = stack.pop ();
System.out.println (" " + pop.data);
if (pop.isLeaf ())
Deque<Integer> path = new ArrayDeque<> ();
Node now = pop;
while (now != null)
path.add (now.data);
now = now.parent;
paths.add (path);
current = pop.right;
if (pop.right != null) pop.right.parent = pop;
System.out.println ("paths = " + paths);
public void allPathsToLeafNodesWithBFS ()
List<Deque<Integer>> paths = new ArrayList<> ();
Queue<Node> queue = new LinkedList<> ();
queue.add (root);
while (!queue.isEmpty ())
Node poll = queue.poll ();
System.out.println ("poll = " + poll);
if (poll.isLeaf ())
Deque<Integer> path = new ArrayDeque<> ();
Node current = poll;
while (current != null)
path.add (current.data);
current = current.parent;
paths.add (path);
if(poll.left != null)
poll.left.parent = poll;
queue.add (poll.left);
if(poll.right != null)
poll.right.parent = poll;
queue.add (poll.right);
System.out.println ("paths = " + paths);
【讨论】:
以上是关于打印树的每个叶子路径而不递归的主要内容,如果未能解决你的问题,请参考以下文章