二叉树的遍历方式

二叉树的遍历方式有四种,分别是前序遍历,中序遍历,后序遍历和层级遍历。

其中前序、中序、后序遍历呢,又可以细分为递归遍历,基于栈的遍历和Morris遍历。层级遍历主要是基于栈的遍历。

下面我们来分别讲讲这几种遍历方式。

递归遍历

递归遍历非常的简单,直接记住套路,直接套即可。

function traversal(root) {
  if(!root) return;
  // 前序
  traversal(root.left);
  // 中序
  travesal(root.right);
  // 后序
}

由二叉树的前中后序遍历的过程可知,前序遍历是 根左右,中序遍历是 左根右,后序遍历是 左右根

你看,刚好对上了上面的代码,上面代码的注释部分就是处理我们当前的节点信息的,也就是 的信息。

基于栈的遍历

前序遍历

前序遍历是先根后左右,但由于栈的特性,必然是先处理根,然后分别入栈右节点,再入栈左节点。

那么处理节点时自然是先处理左节点后处理右节点了。

funtion preorderTraversal(root) {
  let res = [];
  let stack = [];
  let node = root;
  while (node) {
    res.push(node.val);
    if (node.right) {
      stack.push(node.right);
    }
    node = node.left;
    if (!node) {
      node = stack.pop();
    }
  }
  return res;
}

中序遍历

在前序、后序遍历中,while 只需要判断当前节点情况就好了,但是中序遍历还需加多一个栈是否为空的判断。

为什么要加多一个栈的判断呢,我在 while 里加多一个判断,只要 node 节点为空了,我就取栈顶元素赋值给它不行吗?

如果这么操作,我们就会进入无限的死循环中了。因为中序遍历是从最左下节点开始的,所以对于一个子树我们需要跑到它最左下节点开始操作。

就比如你处理了一颗子树的最左下节点了,在 while 里我们又把 node 赋值到当前节点的父节点了,其必是又要跑到最左下节点开始操作的,那么死循环开始了。

function inorderTraversal(root) {
  let res = [];
  let stack = [];
  let node = root;
  while (node || stack.length) {
    while (node) {
      stack.push(node);
      node = node.left;
    }
    node = stack.pop();
    res.push(node.val);
    node = node.right;
  }
  return res;
}

后序遍历

后序遍历是左右根,也是因为栈的特性,把节点的子节点入栈时,需要注意一点点,先入栈左节点,后入栈右节点。

处理元素时,先处理当前根节点,然后处理右节点,再处理左节点。此时我们处理的元素倒转一下就是后序遍历的结果了。

(当然也可以直接调用Javascript提供的数组方法unshift,那就不要倒转结果集了。)

function postorderTraversal(root) {
  let res = [];
  let stack = [];
  let node = root;
  while (node) {
    if (node.left) {
      stack.push(node.left);
    }
    if (node.right) {
      stack.push(node.right);
    }
    res.push(node.val);
    node = stack.pop();
  }
  res = res.reverse();
  return res;
}

前、中、后序遍历,我们的 while 循环都是要有一个共同的判断 判断当前节点,而中序遍历呢需要加多一个栈是否为空的判断。

层级遍历

层级遍历就更简单了,就是从根到叶子结点,从左到右的遍历每一层。话不多说,直接上代码。

function levelTraversal(root) {
  if (!root) return [];
  let res = [];
  let stack = [root];
  while (stack.length) {
    let node = stack.shift();
    res.push(node.val);
    if (node.left) {
      stack.push(node.left);
    }
    if (node.right) {
      stack.push(node.right);
    }
  }
  return res;
}

Morris遍历

posted @ 2021-01-28 22:30  浪荡&不羁  阅读(128)  评论(0编辑  收藏  举报