二叉树遍历 递归与非递归解法
标签:编程基础 算法 树 Java
1. 先序遍历二叉树
递归解法。 思路很简单,先访问当前节点,然后递归访问当前节点的左右子树。
/* public class BinTreeNode {
public int val;
public BinTreeNode left;
public BinTreeNode right;
}
*/
public static void preOrder(BinTreeNode root){
if(root == null) return;
visit(root); //访问节点
preOrder(root.left);
preOrder(root.right);
}
非递归解法。思路是利用栈结构模拟递归调用时的现场还原,步骤如下:
(1)访问当前节点(do something),把当前节点压栈,并循环进入左子树;
(2)当左子树为空,当前节点出栈,并则进入右子树,以右子树为当前节点再次如(1)执行;
(3)当栈为空,则遍历完毕。
public static void preOrder(BinTreeNode root){
Stack<BinTreeNode> stack = new Stack<>();
BinTreeNode p = root;
while(p != null || !stack.isEmpty()){
if(p != null){
visit(p); //访问节点
stack.push(p);
p = p.left;
}
else{
p = stack.pop();
p = p.right;
}
}
}
2. 中序遍历二叉树
递归解法。 思路很简单,先递归访问当前节点的左子树,再访问当前节点,最后递归访问当前节点的右子树。
/* public class BinTreeNode {
public int val;
public BinTreeNode left;
public BinTreeNode right;
}
*/
public static void inOrder(BinTreeNode root){
if(root == null) return;
inOrder(root.left);
visit(root); //访问节点
inOrder(root.right);
}
非递归解法。思路与先序遍历类似,步骤如下:
(1)从当前节点,把当前节点压栈,并循环进入左子树;
(2)当左子树为空,当前节点出栈,访问当前出栈节点(do something),并则进入右子树,以右子树为当前节点再次如(1)执行;
(3)当栈为空,则遍历完毕。
public static void inOrder(BinTreeNode root){
Stack<BinTreeNode> stack = new Stack<>();
BinTreeNode p = root;
while(p != null || !stack.isEmpty()){
if(p != null){
stack.push(p);
p = p.left;
}
else{
p = stack.pop();
visit(p); //访问节点
p = p.right;
}
}
}
3. 后序遍历二叉树
递归解法。 思路很简单,先递归访问当前节点的左右子树,再访问当前节点。
/* public class BinTreeNode {
public int val;
public BinTreeNode left;
public BinTreeNode right;
}
*/
public static void postOrder(BinTreeNode root){
if(root == null) return;
postOrder(root.left);
postOrder(root.right);
visit(root);
}
非递归解法。后序遍历不能使用先序遍历和中序遍历的思想,是三种遍历中比较难的。
后序遍历的访问顺序是"左子节点","右子节点","父节点"。因此需要一种手段保证一个节点的执行在左右孩子节点之后,此处加入pre指针来记录上一次访问的节点。思路是
(1)对于当前节点,先将其入栈;
(2)循环判断栈顶的节点curr,如果该节点不存在左右孩子(叶节点),或者左右孩子已被访问了,则该节点可以访问了(do something),访问后将其出栈,并使pre指向curr。否则,将curr的右子节点入栈,再将curr的左子节点的入栈(按照"后进先出"的原则,这样入栈保证左子节点比右子节点先处理)。
(3)栈为空时,则遍历完毕。
public static void postOrder(BinTreeNode root){
Stack<BinTreeNode> stack = new Stack<>();
BinTreeNode curr;
BinTreeNode pre = null;
stack.push(root);
while(!stack.isEmpty()){
curr = stack.peek();
if((curr.left == null && curr.right == null) ||
(pre != null && (pre == curr.left || pre == curr.right))){
visit(curr); //访问节点
stack.pop();
pre = curr;
}
else{
if(curr.left != null) stack.push(curr.left);
if(curr.right != null) stack.push(curr.right);
}
}
}