二叉树中序遍历(递归+非递归)Java


一、结构

在这里插入图片描述

二、遍历二叉树

这块内容是二叉树最核心的部分。不但要掌握七种遍历的写法,前、中、后序的递归、非递归写法+层次遍历,还有学会(1)用前、中、后序遍历数组创建二叉树;(2)用一维数组存储二叉树。

1.中序遍历(递归)

实现的思路与前序遍历非常类似。主要的不同点是访问节点的顺序不同,中序遍历的访问顺序是 左儿子-根节点-右儿子。

代码

public void inOrderRecur(Node root) {
		if (root == null) {
			return;
		}
		inOrderRecur(root.left);
		System.out.print(root.data + " -> ");
		inOrderRecur(root.right);
	}

注意:这个代码是不是很眼熟呢?其实就是把前序遍历中的两行代码调了个位置。

图解

初始。
在这里插入图片描述
第一步:
(1)执行inOrderRecur(Node root)方法,root不为null,于是调用preOrderRecur(root.left)方法,访问节点B;
(2)B不为空,继续调用inOrderRecur(B.left)方法,访问节点D;
(3)D不为空,调用inOrderRecur(D.left)方法,为空,返回;
(4)打印“D”。
在这里插入图片描述
第二步:
(1)然后调用inOrderRecur(D.right)方法,访问节点H;
(2)节点H不为空,递归调用inOrderRecur(H.left)方法,D.left为空,返回;
(3)打印“H” 。
在这里插入图片描述
第三步:
(1)递归调用inOrderRecur(H.right)方法,D.right为空,返回;
(2)打印“H”的方法结束,返回上一级递归方法,即打印“D”的方法,这个方法也执行完毕;
(3)继续向上返回,即打印节点B的方法,打印节点“B”。
在这里插入图片描述
第四步:
(1)调用inOrderRecur(B.right)方法,访问节点E;
(2)E不为空,继续调用inOrderRecur(E.left)方法,访问节点I;
(3)I不为空,调用inOrderRecur(I.left)方法,I.left为空,返回;
(4)打印“I”。
在这里插入图片描述
第五步:
(1)调用inOrderRecur(I.right)方法,I.right为空,返回;
(2)打印I的方法结束,返回上一级递归方法,即打印“E”的方法,打印“E”。
在这里插入图片描述
第六步:
(1)调用inOrderRecur(E.right)方法,访问节点J;
(2)节点J不为空,调用inOrderRecur(J.left)方法,J.left为空,返回;
(3)打印“J”。
在这里插入图片描述
第七步:
(1)调用inOrderRecur(J.right)方法,J.right为空,返回;
(2)打印“E”的方法结束,向上返回,即打印“B”的方法;
(3)打印“B”的方法也执行完毕,继续向上返回,即打印“A”的方法,打印“A”。

在这里插入图片描述
第八步:
(1)调用inOrderRecur(A.right)方法,访问节点C;
(2)节点C不为空,继续调用inOrderRecur(C.left)方法,访问节点F;
(3)节点F不为空,调用inOrderRecur(F.left)方法,F.left为空,返回;
(4)打印F。
在这里插入图片描述
第九步:
在这里插入图片描述
第十步:
在这里插入图片描述
打印顺序:DHBIEJAFCG

2.中序遍历(非递归)

代码

public void inOrder() {
		Node current = root;
		//把LinkedList作为栈使用
		LinkedList<Node> s = new LinkedList<Node>();
		while (current != null || !s.isEmpty()) {
			while (current != null) {
				s.addFirst(current);
				current = current.left;
			}
			if (!s.isEmpty()) {
				current = s.removeFirst();
				System.out.print(current.data + " -> ");
				current = current.right;
			}
		}
	}

图解

初始:
在这里插入图片描述
第一步:
(1)s.addFirst(current);
(2)A.left不为空,把节点B放入栈中;
(3)B.left不为空,把节点D放入一栈中;

在这里插入图片描述

第二步:
(1)D.left为空,跳出while循环;
(2)取出节点D,打印“D”;
(3)D.right是节点H。
在这里插入图片描述

第三步:
(1)D.right即节点H不为空,执行内存while循环,把节点H放入栈中;
(2)H.left为空,跳出while循环。
在这里插入图片描述

第四步:
(1)取出节点H,打印“H”;
(2)H.right为空,不执行内层while循环;
(3)取出节点B,打印“B”;
(4)B.right是节点E。
在这里插入图片描述

第五步:
(1)B.right即节点E,不为空,执行内层while循环,将节点E放入栈中;
(2)E.left不为空,将节点I放入栈中;
(3)I.left为空跳出while循环。
在这里插入图片描述

第六步:
(1)取出节点I,打印“I”;
(2)I.right为空,不进入内存while循环;
(3)从栈中取出节点E,打印“E”;
(4)E.right为节点J。
在这里插入图片描述

第七步:
(1)E.right即节点J,不为空,执行内层while循环,将节点J放入栈中;
(2)J.left为空,跳出while循环;
在这里插入图片描述

第八步:
(1)取出节点J,打印“J”;
(2)J.right为空,不执行内层while循环;
(3)取出节点A,打印“A”;
(4)A.right是节点C;
在这里插入图片描述

第九步:
(1)A.right即节点C,不为空,放入栈中;
(2)C.left是节点F,把节点F放入栈中;
(3)F.left为空,跳出while循环。
在这里插入图片描述

第十步:
(1)取出节点F,打印“F”;
(2)F.right为空,不执行内层while循环;
(3)取出节点C,打印“C”;
(4)C.right是节点G。
在这里插入图片描述

第十一步:
(1)节点G,不为空,放入栈中;
(2)G.left为空,跳出while循环。
在这里插入图片描述

第十二步:
(1)取出节点G,打印“G”;
(2)G.right为空且栈为空,不执行外层while循环,方法结束。
在这里插入图片描述

打印顺序:DHBIEJAFCG

  • 26
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 二叉树中序遍历非递归实现需要借助栈来实现。具体步骤如下: 1. 首先将根节点入栈; 2. 当栈不为空时,取出栈顶节点,如果该节点有左子树,则将其左子树入栈; 3. 如果该节点没有左子树,则访问该节点,并将其右子树入栈; 4. 重复步骤2和步骤3,直到栈为空。 下面是Java代码实现: ```java public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); TreeNode cur = root; while (cur != null || !stack.isEmpty()) { if (cur != null) { stack.push(cur); cur = cur.left; } else { cur = stack.pop(); res.add(cur.val); cur = cur.right; } } return res; } ``` 其中,TreeNode是二叉树的节点类,val表示节点值,left和right表示左右子节点。 ### 回答2: 二叉树中序遍历是指按照左子树、根节点、右子树的顺序遍历二叉树。通常,我们使用递归算法来实现二叉树的遍历操作。然而,递归算法利用了系统的函数调用栈,当二叉树的高度非常大时,递归可能会导致栈溢出的问题。因此,我们需要考虑使用非递归的方式来实现二叉树中序遍历。 以下是一种基于栈的非递归中序遍历的思路: 1. 首先,创建一个栈和一个指针指向二叉树的根节点。 2. 如果指针不为空或者栈不为空,则继续遍历二叉树。 3. 当指针不为空时,将指针指向的节点压入栈中,并将指针指向其左子节点。 4. 当指针为空时,说明左子树已经遍历完毕,此时从栈中弹出一个节点并访问它,并将指针指向其右子节点。 5. 重复步骤3和4,直到指针为空且栈为空。 通过以上步骤,我们可以按照中序遍历的顺序遍历整个二叉树,且不使用递归算法。在每次遍历时,会将当前节点的左子节点全部入栈,然后再访问栈顶节点、访问右子节点。通过栈的结构,能够保持遍历顺序并避免出现栈溢出的问题。 这种非递归中序遍历实现方式具有较好的效率和空间利用率,适用于各种规模的二叉树的遍历。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值