Binary Tree Postorder Traversal

题目

Given a binary tree, return the postorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3

return [3,2,1].

Note: Recursive solution is trivial, could you do it iteratively?

要求求二叉树后序遍历结果,且是非递归的算法。

解题思路

   二叉树后序遍历是指根结点相对于左右子树节点的遍历顺序,后序遍历访问顺序是左子树、右子树根结点。对于这个题目有两种解法,第一种是方法是:用栈来存储待访问的结点,如果栈非空,弹出一个节点,对于这个结点,如果它的左子树和右子树均为空,则肯定输出该节点信息;如果左子树不为空但右子树为空,当左子树已经访问(这里的访问表示已经输出值),下一个访问的结点肯定就是该节点;如果左子树为空但右子树不为空,当右子树已经访问,下一个访问的结点肯定也是该节点;如果左子树右子树均不为空,访问顺序肯定就是左子树、右子树和该节点,所以如果右子树已经访问,则下一个访问的结点肯定也是该节点;对于其他情况,该节点右子树不为空,则右结点压栈,左子树不为空,则左结点压栈。因为栈的特殊性,所以压栈顺序是相反的。因此,当访问一个节点时,我们记录该节点,如果下次碰到该节点的父节点,就通过判断来访问父节点。于是,有了下面的代码(不清楚的建议手动模拟一下):

public List postorderTraversal(TreeNode root) {
	List list = new ArrayList();
	if (root == null) {
		return list;
	}
	Stack stack = new Stack();
	TreeNode preNode = null;
	TreeNode curNode = null;
	stack.push(root);
	while (!stack.isEmpty()) {
		curNode = stack.peek();
		if ((curNode.left == null && curNode.right == null)
				|| (preNode != null && (curNode.left == preNode || curNode.right == preNode))) {
			preNode = curNode;
			list.add(curNode.val);
			stack.pop();
		} else {
			if (curNode.right != null) {
				stack.push(curNode.right);
			}
			if (curNode.left != null) {
				stack.push(curNode.left);
			}
		}
	}
	return list;
}

第二种思路可能更难想到,算法比较简单容易理解,对于后序遍历的左子树、右子树和根结点的顺序,逆向顺序就是根结点、右子树和左子树。因此,栈来存储待访问的结点,如果栈非空,弹出一个节点,对于这个结点,直接将它的值加入链表,如果左子树非空,左结点入栈;右子树非空,右结点入栈。遍历完毕,将链表反转返回即可。

public List postorderTraversal2(TreeNode root) {
	List list = new ArrayList();
	if (root == null) {
		return list;
	}
	Stack stack = new Stack();
	TreeNode curNode = null;
	stack.push(root);
	while (!stack.isEmpty()) {
		curNode = stack.pop();
		list.add(curNode.val);
		if (curNode.left != null) {
			stack.push(curNode.left);
		}
		if (curNode.right != null) {
			stack.push(curNode.right);
		}			
	}
	Collections.reverse(list);
	return list;
}
对于上面两种算法,在leetcode里均通过,但第一种所用时间短一些。








你可能感兴趣的:(leetcode,二叉树后序遍历,非递归)