1简述
二叉树的前序遍历和后序遍历的递归实现是相对容易实现的,而且非常便于理解。
对于前序遍历
首先访问当前节点;
如果左子树非空,前序遍历左子树;
如果右子树非空,前序遍历右子树
对于后序遍历
如果左子树非空,后序遍历左子树;
如果右子树非空,后序遍历右子树;
最后访问当前节点
2非递归实战
当采用非递归方法来说实现时,就要略微复杂一些了。
首先来看前序遍历
根据前序遍历的定义,我们总是访问当前节点,访问左子树,访问当前节点,访问左子树。。。只有当左子树为空时才会去访问右子树,接着就是重复这一过程;而当右子树为空的时候,我们要退回到上一个节点,查看上一个节点右子树是否为空,若非空,接着重复访问过程。因为有一个后退的过程,所以我们考虑用栈来保存访问经过的节点。在每次循环过程中,我们总会先判断左子树是否已经被访问过,所以我们需要对已经访问过的节点进行标记。对于LeetCode上的原题(网址https://oj.leetcode.com/problems/binary-tree-preorder-traversal/)来说,具体代码过程如下:
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new LinkedList<Integer>(); // List to save the result of Binary Tree Preorder Traversal
if(root == null) {
return result;
}
Set<TreeNode> set = new HashSet<TreeNode>(); // Set to save the TreeNode that has been visited.
Stack<TreeNode> stk = new Stack<TreeNode>(); // Stack to allow to step back to previous TreeNode
TreeNode currentNode;
// First, visit the root
set.add(root);
stk.push(root);
result.add(root.val);
while(!stk.isEmpty()) {
currentNode = stk.peek(); // Get the top TreeNode that has been visited but not pop it.
while(currentNode.left != null && !set.contains(currentNode.left)) { // Has left child but not been visited, just visit it!
currentNode = currentNode.left;
set.add(currentNode);
stk.push(currentNode);
result.add(currentNode.val);
}
// Visit until the left is null
// Check whether has right child and if it is visited
if(currentNode.right != null && !set.contains(currentNode.right)) {
currentNode = currentNode.right;
set.add(currentNode);
stk.push(currentNode);
result.add(currentNode.val);
} else { // Has no right child, just pop it out
stk.pop();
}
}
return result;
}
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
if(root == null) {
return result;
}
Set<TreeNode> set = new HashSet<TreeNode>();
Stack<TreeNode> stk = new Stack<TreeNode>();
stk.push(root);
TreeNode currentNode;
while(!stk.isEmpty()) {
currentNode = stk.peek(); // Get the top TreeNode but not pop it
while(currentNode.left != null && !set.contains(currentNode.left)) { // Walk until left child is null, and check whether it has been visited
stk.push(currentNode.left);
currentNode = currentNode.left;
}
if(currentNode.right != null && !set.contains(currentNode.right)) { // push the right child if it has not been visited
stk.push(currentNode.right);
} else { // Has no right child or it has been visited before, just visit it!
set.add(currentNode);
result.add(currentNode.val);
stk.pop();
}
}
return result;
}