算法:迭代实现二叉树的中序、前序和后序遍历

365 阅读2分钟

「这是我参与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;
}

结语

如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。

文章如有错误之处,希望在评论区指正🙏🙏

欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后