二叉树遍历 递归与非递归解法

标签:编程基础 算法 树 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);
		}
	}
}
posted @ 2017-03-18 09:24  斑鱼  阅读(238)  评论(0编辑  收藏  举报