前言:
力扣链接:145.二叉树的后序遍历
不同于前文中提到的前序、后序的迭代遍历方式,前序遍历的顺序是中左右,先访问的元素是中间节点。要处理的元素也是中间节点,由于前序遍历访问的节点与处理的节点为同一节点。而对于后序遍历实际上只是对前序遍历进行了一个数组的翻转,本质与前序遍历并无区别。
而对于中序遍历,中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点,这就造成了处理顺序和访问顺序是不一致。
基础介绍:
-
- 二叉树的中序遍历是一种按照特定顺序访问二叉树节点的方法,其顺序为 “左 - 根 - 右”。这意味着在遍历二叉树时,首先会递归地遍历节点的左子树,然后访问当前节点,最后再递归地遍历节点的右子树。
- 例如,对于下面这棵简单的二叉树:
1
/ \
2 3
/ \ / \
4 5 6 7
- 其中序遍历的顺序是 4、2、5、1、6、3、7。先从根节点 1 开始,它的左子树的根节点是 2,继续往左,最左边的节点是 4,所以先访问 4;然后访问 4 的父节点 2,接着访问 2 的右子树的节点 5;此时左子树遍历完成,访问根节点 1;再遍历根节点 1 的右子树,右子树的根节点是 3,其左子树最左边节点是 6,访问 6,接着访问 6 的父节点 3,最后访问 3 的右子树的节点 7。
首先定义两个数组,一个用于存储中序遍历的数组,另一个用于模仿栈
将根节点(root)赋给cur
使用while循环实现迭代
判断条件:
1.是栈不能为空
2.cur不能是null:这是因为当我们将根节点的左边全部进行遍历后会使得栈变为空的,
此时右边却还没有进行遍历,因此需要加上对cur是否为空值的判断,才能将右边进行全部的遍历。
var inorderTraversal = function (root) {
let stack=[]
let arr=[]
let cur=root
while(stack.length||cur){
if(cur){
stack.push(cur)
cur=cur.left
}
else{
cur=stack.pop()
arr.push(cur.val)
cur=cur.right
}
}
return arr
};
处理左子树节点并压入栈(
if (cur)分支) :
- 当
cur不为null时,意味着当前节点存在,按照中序遍历 “左 - 根 - 右” 的顺序,首先要处理左子树,所以先将当前节点cur压入栈stack中,然后更新cur为其左子节点(cur = cur.left),这样在下一轮循环中,如果左子节点还存在,就会继续将其左子节点压入栈,不断深入左子树,直到遇到左子树的叶子节点(左子节点为null)。弹出栈顶节点并处理(
else分支) :
- 当
cur为null时,说明已经到达了当前节点左子树的最底层(左子节点都已经处理完或者本身就没有左子树),此时按照中序遍历顺序,应该访问根节点了,所以通过cur = stack.pop()从栈中弹出一个节点,这个节点就是当前子树的根节点(按照遍历顺序,之前已经把它的左子树节点都压入栈了,现在左子树处理完了,该它了)。- 接着将弹出节点的值
cur.val存入结果数组arr中,这一步实现了对根节点值的记录,符合中序遍历 “左 - 根 - 右” 中访问根节点的要求。- 最后,将
cur更新为其右子节点(cur = cur.right),准备去处理当前节点的右子树,开始下一轮循环,继续探索右子树的节点情况,重复上述过程,直到整个二叉树的所有节点都被访问并记录到arr数组中。