阅读 88

JS实现二叉树的前序、中序、后续、层序遍历

前序遍历

LeetCode题目

递归

var preorderTraversal = function(root) {
  const res = [];
  // 递归函数
  function _preorder(node) {
    if (!node) return;
    res.push(node.val);
    _preorder(node.left);
    _preorder(node.right);
  }
  _preorder(root);
  return res;
};
复制代码

迭代

通过栈数据结构(先进后出),我们可以将父节点压入栈,对栈执行出栈操作,每次将出栈的节点的右孩子先压入栈,其次压入左孩子。这样就可以做到先遍历父节点,在遍历左孩子部分,后遍历右孩子部分。

var preorderTraversal = function(root) {
  if (!root) return [];
  const stack = [root];
  const res = [];
  while(stack.length) {
    // 出栈
    const cur = stack.pop();
    res.push(cur.val);
    // 子节点存在压入栈中,先右再左
    cur.right && stack.push(cur.right);
    cur.left && stack.push(cur.left);
  }
  return res;   
};
复制代码

中序遍历

LeetCode题目

递归

var inorderTraversal = function(root) {
  const res = [];
  // 递归函数
  function _inorder(node) {
    if (!node) return;
    _inorder(node.left);
    res.push(node.val);
    _inorder(node.right);
  }
  _inorder(root);
  return res;
};
复制代码

迭代

我们同样可以使用栈结构来实现中序遍历,因为中序遍历左子树是优先遍历,所以父节点要先于子树的节点优先压入栈中,每当我们压入节点时,都要把节点的左子树的所有左节点压入栈中。

var inorderTraversal = function(root) {
  if (!root) return [];
  const stack = [];
  let cur = root;
  const res = [];
  while (stack.length || cur) {
    // 左节点都先压入栈
    while (cur) {
      stack.push(cur);
      cur = cur.left;
    }
    const node = stack.pop();
    res.push(node.val);
    if (node.right != null) {
      cur = node.right;
    }
  }
  return res;
};
复制代码

后序遍历

LeetCode题目

递归

var postorderTraversal = function(root) {
  const res = [];
  // 递归函数
  function _postorder(node) {
    if (!node) return;
    _postorder(node.left);
    _postorder(node.right);
    res.push(node.val);
  }
  _postorder(root);
  return res;
};
复制代码

迭代

后序遍历是父节点需要最后被遍历。但其实可以跟前序遍历的实现方式上差不多,只不过在插入数组中,我们总是在头部插入,这样先被插入的节点值一定是相对于左右孩子后面的。

var postorderTraversal = function(root) {
  if (!root) return null;
  const res = [];
  const stack = [root];
  while (stack.length) {
    const cur = stack.pop();
    // 总是头部插入,先被插入的在后面。
    res.unshift(cur.val);
    cur.left && stack.push(cur.left);
    cur.right && stack.push(cur.right);
  }

  return res;
};
复制代码

层序遍历

LeetCode题目

递归

var levelOrder = function(root) {
  const res = [];
  function _levelOrder(node, level) {
    if (!node) return null;
    // 当前层数组初始化
    res[level] =  res[level] || [];
    res[level].push(node.val);
    // 下一层 +1
    _levelOrder(node.left, level + 1);
    _levelOrder(node.right, level + 1);
  }
  _levelOrder(root, 0);

  return res;
};
复制代码

迭代

我们使用队列来保存节点,每轮循环中,我们都取一层出来,将它们的左右孩子放入队列。

var levelOrder = function(root) {
  if (root == null) return [];
  const ans = [];
  let level = 0;
  const queue = [root];
  while(queue.length) {
    ans.push([]);
    const len = queue.length;
    // 通过遍历,提前执行完一层的所有元素,层级level就可以+1
    for (let i = 0; i < len; i++) {
      const node = queue.shift();
      ans[level].push(node.val);
      node.left && queue.push(node.left);
      node.right && queue.push(node.right);
    }
    level++;
  }
  return ans;
};
复制代码

总结

关于二叉树的前序、中序、后续遍历,使用递归的方法不用多说,主要是迭代方法,通过对的应用,对节点不同顺序的压入栈中,从而实现不同顺序的遍历。二叉树的层序遍历迭代方式则是通过对队列的应用。

关注下面的标签,发现更多相似文章
评论