zoukankan      html  css  js  c++  java
  • 二叉树的遍历方式

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

    其中前序、中序、后序遍历呢,又可以细分为递归遍历,基于栈的遍历和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遍历

  • 相关阅读:
    Python校验文件MD5值
    no acceptable C compiler found in $PATH解决办法
    PRD是什么
    项目中PO、PM的职责区分
    vue-cli中打包之后css加载顺序有错
    vue-cli中打包图片路径错误
    vue2.0的父子组件数据传递
    vue中style的用法
    vue中class的用法
    angular淘宝购物车案例
  • 原文地址:https://www.cnblogs.com/AuKing/p/14342376.html
Copyright © 2011-2022 走看看