「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
Hope is a good thing, maybe the best of things. And no good thing ever dies.
前言
前面的文章,学习了使用递归的方式去进行二叉树的中序、前序和后序遍历,今天要使用迭代方式去实现二叉树的中序、前序和后序遍历。
递归方式:
我们用迭代的方式实现递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其他都相同。
递归和迭代的复杂度分析
递归的复杂度:
- 时间复杂度:
O(n),其中n为二叉树节点的个数。二叉树的遍历中每个节点会被访问一次且只会被访问一次。 - 空间复杂度:
O(n)空间复杂度取决于递归的栈深度,而栈深度在二叉树为一条链的情况下会达到O(n)的级别。
迭代的复杂度
- 时间复杂度:
O(n),其中n为二叉树节点的个数。二叉树的遍历中每个节点会被访问一次且只会被访问一次。 - 空间复杂度:
O(n)。空间复杂度取决于栈深度,而栈深度在二叉树为一条链的情况下会达到O(n)的级别
中序遍历
var inorderTraversal = function(root) {
const res = [];
const stk = []; // 模拟一个执行栈
while (root || stk.length) {
while (root) {
stk.push(root);
root = root.left;
}
root = stk.pop();
res.push(root.val);
root = root.right;
}
return res;
};
或者
var inorderIteration = function (root) {
let res = [];
let stk = []; // 模拟一个执行栈
while(root || stk.length) {
if(root.left) {
stk.push(root)
root = root.left;
} else if(root.right) {
res.push(root.val)
root = root.right
} else if(!root.left && !root.right){
res.push(root.val)
root = stk.pop();
if(root) {
root.left = null
}
}
}
return res;
}
前序遍历
根节点 - 左节点 - 右节点
var preorderIteration = function(root) {
const res = [];
const stack = [];
root && stack.push(root)
// 先输出二叉树根节点,之后依次输出二叉树的左和右
while(stack.length > 0) {
let cur = stack.pop()
// 出栈顶元素,当前二叉树根节点
res.push(cur.val)
// 先入栈的元素后输出,所以先入栈当前节点右孩子,再入栈左孩子
cur.right && stack.push(cur.right)
cur.left && stack.push(cur.left)
}
return res
}
后序遍历
function postorderIteration(root) {
let res = [];
let stack = []; // 模拟一个执行栈
while (root || stack.length) {
if (root.left) {
// 如果存在左子树
stack.push(root);
root = root.left;
} else if (root.right) {
// 如果存在右子树
stack.push(root);
root = root.right;
} else {
// 获取当前值
res.push(root.val);
// 取出执行栈的数据
root = stack.pop();
if (root && root.left) {
root.left = null;
} else if (root && root.right) {
root.right = null;
}
}
}
return res;
}
结语
如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。
文章如有错误之处,希望在评论区指正🙏🙏
欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后 」