二叉树 求节点、深度、前序、中序、后序遍历

package xcc.test;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

import xcc.bean.TreeNode;

public class TestErCha {
	
	/**
	 * 第一种求二叉树节点个数(利用递归)
	 * (1)如果二叉树为空,节点个数为0
	 * (2)如果二叉树不为空,则节点个数=左子树节点+右子树节点+1
	 * 原理:递归中的root.left和root.right进行子节点的查找。之后进行+1操作
	 */
	public static int getNodeNumRec(TreeNode root) {  
        if (root == null) {  
            return 0;  
        } else {  
            return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1;  
        }  
    } 
	
	/**
	 * 第二种求二叉树节点个数(利用迭代)
	 * (1)从队头位置移除
	 * (2)如果有左孩子,加到队尾
	 * (3)如果有右孩子,加到队尾
	 * 原理:从对头开始移除,如果包含左节点,则添加在queue中,包含右节点,则添加在queue中,并移除当前节点。
	 */
	public static int getNodeNumIte(TreeNode root){
		if(root == null){
			return 0;
		}
		int count = 1;
		Queue<TreeNode> queue = new LinkedList<TreeNode>();
		queue.add(root);
		while(!queue.isEmpty()){
			TreeNode treeNode = queue.remove();
			if(treeNode.left != null){
				queue.add(treeNode.left);
				count++;
			}
			if(treeNode.right != null){
				queue.add(treeNode.right);
				count++;
			}
		}
		return count;
	}
	
	/**
	 * 第一种求二叉树深度(利用递归)
	 * (1)如果二叉树为空,深度为0
	 * (2)如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1
	 */
	public static int getDepthRec(TreeNode root) {  
        if (root == null) {  
            return 0;  
        } 
        int left = getDepthRec(root.left);
        int right = getDepthRec(root.right);
        return Math.max(left, right) + 1;
    } 
	
	/**
	 * 第二种求二叉树深度(利用迭代)
	 * (1)首先移除对头
	 * (2)减少当前node数量
	 * (3)如果有左右节点,则需要加左右节点追加到queue中,并记录个数
	 * (4)当前node数量为0时,证明当前层全部遍历完
	 * (5)根据记录的个数,进行一层的遍历
	 */
	public static int getDepthIte(TreeNode root) {  
        if (root == null) {  
            return 0;  
        } 
        int depth = 0;             //深度
        int currentLevelNodes = 1; //当前Level,node的数量
        int nextLevelNodes = 0;    //下一层node的数量
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
		queue.add(root);
        while(!queue.isEmpty()){
        	TreeNode treeNode = queue.remove();
        	currentLevelNodes--;
        	if(treeNode.left != null){
				queue.add(treeNode.left);
				nextLevelNodes++;
			}
			if(treeNode.right != null){
				queue.add(treeNode.right);
				nextLevelNodes++;
			}
			if(currentLevelNodes == 0){// 说明已经遍历完当前层的所有节点
				depth++;               // 增加高度
				currentLevelNodes = nextLevelNodes;// 初始化下一层的遍历  
				nextLevelNodes = 0;
			}
        }
        return depth;
    } 
	
	/**
	 * 第一种前序遍历(递归)
	 * (1)如果二叉树为空,空操作
	 * (2)如果二叉树不为空,访问根节点,前序遍历左子树,前序遍历右子树
	 */
	public static void preorderTraversalRec(TreeNode root) {  
        if (root == null) {  
            return;  
        }  
        System.out.print(root.val + " ");  
        preorderTraversalRec(root.left);  
        preorderTraversalRec(root.right);  
    }  
	
	/**
	 * 第二种前序遍历(迭代)
	 * (1)如果二叉树为空,空操作
	 * (2)借助stack(栈)来实现,先进后出
	 * (3)先让右孩子就入,再让左孩子进入
	 */
	public static void preorderTraversalIte(TreeNode root) {  
        if (root == null) {  
            return;  
        }  
        Stack<TreeNode> stack = new Stack<TreeNode>();      // 辅助stack  
        stack.push(root);  
          
        while( !stack.isEmpty() ){  
            TreeNode cur = stack.pop();     // 出栈栈顶元素  
            System.out.print(cur.val + " ");  
              
            // 关键点:要先压入右孩子,再压入左孩子,这样在出栈时会先打印左孩子再打印右孩子  
            if(cur.right != null){  
                stack.push(cur.right);  
            }  
            if(cur.left != null){  
                stack.push(cur.left);  
            }  
        }    
    }
	
	/**
	 * 第一种中序遍历(递归)
	 * (1)如果二叉树为空,空操作
	 * (2)如果二叉树不为空,中序遍历左子树, 访问根节点,中序遍历右子树
	 */
	public static void inorderTraversalRec(TreeNode root) {  
        if (root == null) {  
            return;  
        }  
        inorderTraversalRec(root.left);  
        System.out.print(root.val + " ");  
        inorderTraversalRec(root.right);  
    }  
	
	/**
	 * 第二种中序遍历(迭代)
	 * (1)用栈先把根节点的所有左孩子都添加到栈内
	 * (2)然后输出栈顶元素,再处理栈顶元素的右子树
	 */
	public static void inorderTraversalIte(TreeNode root){  
        if(root == null){  
            return;  
        }  
        Stack<TreeNode> stack = new Stack<TreeNode>();  
        TreeNode cur = root;  
          
        while( true ){  
            while(cur != null){     // 先添加一个非空节点所有的左孩子到栈  
                stack.push(cur);  
                cur = cur.left;  
            }  
              
            if(stack.isEmpty()){  
                break;  
            }  
                  
            // 因为此时已经没有左孩子了,所以输出栈顶元素  
            cur = stack.pop();  
            System.out.print(cur.val + " ");  
            cur = cur.right;    // 准备处理右子树  
        }  
    }
	
	/** 
     * 第一种后序遍历(递归)  
     * (1)如果二叉树为空,空操作  
     * (2)如果二叉树不为空,后序遍历左子树,后序遍历右子树,访问根节点 
     */  
    public static void postorderTraversalRec(TreeNode root) {  
        if (root == null) {  
            return;  
        }  
        postorderTraversalRec(root.left);  
        postorderTraversalRec(root.right);  
        System.out.print(root.val + " ");  
    } 
    
    /** 
     * 第二种后序遍历(迭代)  
     * (1)如果二叉树为空,空操作  
     * (2)如果二叉树不为空,后序遍历左子树,后序遍历右子树,访问根节点 
     */ 
    public static void postorderTraversalIte(TreeNode root) {  
        if (root == null) {  
            return;  
        }  
          
        Stack<TreeNode> s = new Stack<TreeNode>();      // 第一个stack用于添加node和它的左右孩子  
        Stack<TreeNode> output = new Stack<TreeNode>();// 第二个stack用于翻转第一个stack输出  
          
        s.push(root);  
        while( !s.isEmpty() ){      // 确保所有元素都被翻转转移到第二个stack  
            TreeNode cur = s.pop(); // 把栈顶元素添加到第二个stack  
            output.push(cur);         
              
            if(cur.left != null){       // 把栈顶元素的左孩子和右孩子分别添加入第一个stack  
                s.push(cur.left);  
            }  
            if(cur.right != null){  
                s.push(cur.right);  
            }  
        }  
          
        while( !output.isEmpty() ){ // 遍历输出第二个stack,即为后序遍历  
            System.out.print(output.pop().val + " ");  
        }  
    }  

	public static void main(String[] args) {
		/*
                 1  
                / \  
               2   3  
              / \   \  
             4  5   6
		 */
		TreeNode r1 = new TreeNode(1);  
        TreeNode r2 = new TreeNode(2);  
        TreeNode r3 = new TreeNode(3);  
        TreeNode r4 = new TreeNode(4);  
        TreeNode r5 = new TreeNode(5);  
        TreeNode r6 = new TreeNode(6);   
          
        r1.left = r2;  
        r1.right = r3;  
        r2.left = r4;  
        r2.right = r5;  
        r3.right = r6; 
 
        
        TestErCha.postorderTraversalRec(r1);	
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值