二叉树(二)| 二叉树的四种遍历(java实现)

二叉树节点的存储结构

	public class TreeNode {
	     int val;
	     TreeNode left;
	     TreeNode right;
	     TreeNode(int x) { val = x; }
	}

先序遍历

先序遍历的顺序为: 根 -> 左 -> 右

1、递归方法很容易实现:

	//(递归)先序遍历   根 > 左>右
	public void preOrderTraveral(TreeNode node) {
		if (node == null) {
			return ;
		}
		System.out.println(node.val);
		preOrderTraveral(node.left);
		preOrderTraveral(node.right);
	}

2、非递归遍历相对复杂一点。过程如下:

  1. 首先申请一个栈stack。
  2. 申明一个当前节点currentNode从node节点开始遍历。
  3. 如果当前节点不为空,先访问当前节点(currentNode),并将当前节点入栈,然后当前节点指向它的左子节点。
  4. 重复循环,直到当前节点到达它的子树的左子叶节点。
  5. 开始出栈,当前对象指向它的右子节点。
  6. 重复步骤3,直到stack为空。
//(非递归---栈实现)先序遍历   根 > 左>右
	public void non_preOrderTraveral(TreeNode node){
		Stack<TreeNode> stack = new Stack<BinaryTree.TreeNode>();
		TreeNode currentNode = node;
		
		while (currentNode!=null || !stack.isEmpty() ) {
			//迭代访问节点的左子节点,并入栈
			while (currentNode!=null) {    //将当前节点的左子节点全部入栈
				System.out.println(currentNode.val);
				stack.push(currentNode);
				currentNode = currentNode.left;
			}
			//如果当前节点没有左子节点,则弹出一个节点,然后从弹出的节点的右子节点开始继续迭代访问左子节点
			if (!stack.isEmpty()) {
				currentNode = stack.pop();
				currentNode = currentNode.right;
			}
		}
		
	}

中序遍历

中序遍历的顺序为:左- > 根 -> 右。

1、递归实现

	//(递归)中序遍历   左 > 根  > 右
	public void inOrderTraveral(TreeNode node) {
		if (node == null) {
			return;
		}
		inOrderTraveral(node.left);
		System.out.println(node.val);
		inOrderTraveral(node.right);
	}

2、非递归实现

具体过程如下:

  1. 申请一个新栈,记为stack,申请一个变量currentNode,初始时令currentNode为头节点;
  2. 先把currentNode节点压入栈中,对以currentNode节点为头的整棵子树来说,依次把整棵树的左子树压入栈中,即不断令currentNode=currentNode.leftChild,然后重复步骤2;
  3. 不断重复步骤2,直到发现currentNode为空,此时从stack中弹出一个节点记为currentNode,打印node的值,并让currentNode= currentNode.right,然后继续重复步骤2;
  4. 当stack为空并且currentNode为空时结束。
//(非递归--)中序遍历   左 > 根  > 右
	public void non_inOrderTraveral(TreeNode node) {
		Stack<TreeNode> stack = new Stack<BinaryTree.TreeNode>();
		TreeNode currentNode = node;
		while (currentNode!=null || !stack.isEmpty()) {
			while (currentNode!=null) {     //将当前节点的左子节点全部入栈
				stack.push(currentNode);
				currentNode = currentNode.left;
			}
			if (!stack.isEmpty()) {
				currentNode = stack.pop();
				System.out.println(currentNode.val);
				currentNode = currentNode.right;
			}
		}
	}

后续遍历

后续遍历的顺序为:左 -> 右 -> 根。

1、递归实现

	//(递归)后续遍历   左 > 右 > 根
	public void postOrderTraveral(TreeNode node) {
		if (node == null) {
			return ;
		}
		postOrderTraveral(node.left);
		postOrderTraveral(node.right);
		System.out.println(node.val);
	}

2、非递归实现

后续遍历需要在上述基础上增加一个flagNode变量来标记是不是右子节点。

    //(非递归)后续遍历   左 > 右 > 根
	public void non_postOrderTraveral(TreeNode node) {
		if (node==null) {
			return;
		}
		Stack<TreeNode> stack = new Stack<BinaryTree.TreeNode>();
		TreeNode currentNode = node;
		TreeNode flagNode = null;
		
		//将当前节点子树中的左节点全部入栈
		while (currentNode!=null) {
			stack.push(currentNode);
			currentNode = currentNode.left;
		}
		while (!stack.isEmpty()) {
			currentNode = stack.pop(); //挨个出栈
			if (currentNode.right==null || currentNode.right == flagNode) {  //如果是右子叶节点则访问
				System.out.println(currentNode.val);
				flagNode = currentNode;
			}else {    //否则继续进栈
				stack.push(currentNode);
				currentNode = currentNode.right;
				while (currentNode!=null) { //一直找到右子节点中的左子叶节点
					stack.push(currentNode);
					currentNode = currentNode.left;
				}
			}
		}
		
	}

层次遍历

二叉树的层次遍历就是按照从上到下、从左到右的顺序访问节点,需要借助一个队列来实现,层次遍历用递归反而不好实现。

	//层次遍历(队列实现)
	public void levelOrderTraveral(TreeNode node) {
		Queue<TreeNode> queue  = new LinkedList<BinaryTree.TreeNode>();
		TreeNode currentNode = node;
		queue.add(currentNode);
		while (!queue.isEmpty()) {
			currentNode = queue.poll();
			System.out.println(currentNode.val);
			if (currentNode.left!=null) {
				queue.add(currentNode.left);
			}
			if (currentNode.right!=null) {
				queue.add(currentNode.right);
			}
		}
	}

后续将会继续介绍二叉树的一些高级特性及实现方式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值