给定一个二叉树,返回它的中序 遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [1,3,2]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
详解:
这道题和我的上一篇二叉树的前序遍历很像,遍历思想是一样的,关键是什么时候输出结果。
- 首先new一个列表(存储结果),new一个栈, 定义一个当前待处理的节点(初始值为root节点)
- 判断当前节点是否为空,为空退出循环,不为空执行第3步。因为是中序遍历,所以当前节点不能直接输入到结果(和前序不一样的地方)
- 判断左子节点,不为空,压栈,更新当前节点,执行第2步(因为是前序遍历,所以左右子节点优先左节点。)
- 此处说明当前节点的左子节点为空,那么需要输出当前节点到结果,然后执行第5步。
- 判断右子节点,不为空,压栈,更新当前节点,执行第2步。
- 这一步分析比较长,写成一段(这一步遍历思想和前序的很像,直接拷贝过来,改一下细节):
-
如果执行到了这里这里,说明当前节点的左右子节点都是空的,且当前节点已经输出到结果(第4步输入的),但是还没有压栈(其实已经没有压栈的必要了,因为结果也输出了,又没有子节点)。这个时候就要考虑他的父节点了,父节点在哪呢?栈里!可以看到上面先执行第三步,那么每一个父节点如果他有左节点,那么他的右节点就没有遍历处理(因为随着循环去处理他的左节点了)。所以现在要依次考虑每一个父节点右子节点(此时不需要考虑父节点的左子节点,不理解的自己去面壁思考)
-
既然依次考虑,所以需要一个循环,如果当前栈顶节点的右子节点不为空,且右子节点不等于当前节点(这个且非常重要,不然就可能会重复处理右子节点),说明当前右子节点还没有处理,此时输出当前节点(因为即将处理他的右子节点),更新当前节点,退出循环,执行第2步。否则直接出栈当前节点,如果他的右子节点是空的,需要输出当前节点(不然如果没有右子节点,会导致该节点不会被输出),接着判断下一个栈顶,直到栈空了
- 至此结束
再详细的思路也不及代码片行,那直接贴代码:
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode tmp = root;
while (tmp != null){
if(tmp.left != null){
stack.push(tmp);
tmp = tmp.left;
continue;
}
list.add(tmp.val);
if(tmp.right != null){
stack.push(tmp);
tmp = tmp.right;
continue;
}
while (true){
if(stack.isEmpty()){
tmp = null;
break;
}
TreeNode peek = stack.peek();
if(peek.right != null && peek.right != tmp){
list.add(peek.val);
tmp = peek.right;
break;
}
tmp = stack.pop();
if(tmp.right == null){
list.add(tmp.val);
}
}
}
return list;
}
-
最后贴一下效率:
-