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


    标签:编程基础 算法 树 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);
    		}
    	}
    }
    
  • 相关阅读:
    postgreSQL入门命令
    JDBC连接数据库
    nano编辑器使用教程
    Linux上vi(vim)编辑器使用教程
    【编程思想】【设计模式】【行为模式Behavioral】状态模式State
    【编程思想】【设计模式】【行为模式Behavioral】Specification
    【编程思想】【设计模式】【行为模式Behavioral】registry
    【编程思想】【设计模式】【行为模式Behavioral】Publish_Subscribe
    【编程思想】【设计模式】【行为模式Behavioral】观察者模式Observer
    【编程思想】【设计模式】【行为模式Behavioral】备忘录模式Memento
  • 原文地址:https://www.cnblogs.com/banyu/p/6571335.html
Copyright © 2020-2023  润新知