前言
之前学习了二叉树的递归遍历,接下来学习下二叉树的迭代遍历。
二叉树的前序遍历-迭代法
题目描述
给你二叉树的根节点 root ,返回它节点值的 前序 **遍历。
示例:
输入: root = [1,null,2,3]
输出: [1,2,3]
思路
- 按照栈的思路来处理这类问题,前序遍历的顺序为
中左右,这里我们推入栈中的顺序为中右左,因为栈的特点为先进后出 - 结束遍历的条件为
栈空
代码
var preorderTraversal = function(root) {
// 栈,结果数组
let stack=[],result=[];
//将根节点推入栈中
stack.push(root);
//当栈不为空时,按照 中右左 的顺序执行逻辑
while(stack.length!=0){
let item=stack.pop();
if(item==null){
continue;
}
result.push(item.val);
if(item.right)stack.push(item.right);
if(item.left) stack.push(item.left);
}
return result;
};
结果
二叉树的后序遍历-迭代法
题目描述:
给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历
示例 1:
输入: root = [1,null,2,3]
输出: [3,2,1]
思路
后续遍历的顺序为左右中,我们首先得到的便是中节点,所以直接按照左右中的 顺序来做,不好做。左右中——中右左,如果我们按照中右左的顺序来遍历,遍历结束后将结果反转便可以得到左右中的结果了。- 逻辑顺序为
中右左,入栈顺序为中左右,因为栈的特点为:先进后出。
代码
var postorderTraversal = function(root) {
// 定义栈,结果数组
let stack=[],result=[];
stack.push(root);
// 以栈是否为空作为是否结束遍历的条件。
while(stack.length!=0){
//弹出栈顶元素
let item=stack.pop();
//若栈顶元素为null,跳过
if(item==null) continue;
// 不为空,将栈顶元素的值放入结果数组中
result.push(item.val);
// 按照左右的顺序,将节点推入栈中
if(item.left) stack.push(item.left);
if(item.right) stack.push(item.right);
}
// 反转结果数组,并返回。
return result.reverse();
};
结果
二叉树的中序遍历-迭代法
题目描述
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例 1:
输入: root = [1,null,2,3]
输出: [1,3,2]
思路
中序遍历的顺序为左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中)。- 需要一个指针去找到左子树的叶子节点,也就是要找到最深层的左节点。
- 结束遍历的条件为:栈为空并且指针为null
代码
var inorderTraversal = function(root) {
// 定义栈,结果数组,当前指针
let stack=[],result=[],cur=root;
// 当栈不为空或者cur!=null时
while(stack.length!=0||cur!=null){
// 如果cur不为null
if(cur){
//将cur推入栈中,并且cur指向cur的left
stack.push(cur);
cur=cur.left;
}
else{
// 否则,弹出栈顶元素,cur指向栈顶元素。
cur=stack.pop();
result.push(cur.val);
// 判断栈顶元素是否有右节点
cur=cur.right;
}
}
return result;
};
结果:
总结
二叉树的遍历分为:迭代遍历和递归遍历,相对而言递归好理解一点,但迭代遍历也不难,关键点在于:采用栈的思想,并弄清楚几种遍历的顺序,理清思路。