算法之二叉树的点点滴滴

136 阅读1分钟

「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战

二叉树简介

  • 一种非常重要的数据结构
  • 五种形态
    • 空二叉树 = 没有根结点 + 没有子节点
    • 只有根结点,没有子节点
    • 根结点 + 左子树
    • 根结点 + 右子树
    • 完全二叉树 = 根结点 + 左子树 + 右子树
  • 节点的度 <= 2

二叉树拥有特别好算的性质

  • 第 i 层: 节点数 <= 2i - 1
  • 深度为 h:节点数 <= 2h - 1
  • n 个叶子节点 + m 个度为 2 的节点:n = m + 1
  • 满二叉树 + n 个节点:深度 = log2n + 1
  • 完全二叉树 + n 个节点:
    • i = 1: 当前节点为根结点
    • i > 1: 父节点编号 = i / 2
    • 2i <= n: 左节点编号 = 2i
    • 2i + 1 <= n: 右节点编号 = 2i + 1

二叉树的遍历

  • 深度遍历(2年前在力扣刷的题,每道题都用去了半天的时间)
    • 前序遍历 【 根 + 左 + 右 】
      • 通过递归方法来进行二叉树的前序遍历
        var preorderTraversal = function(root, arr=[]) { 
            if(root) { 
                arr.push(root.val)  // 根
                preorderTraversal(root.left, arr)  // 左子树(递归)
                preorderTraversal(root.right, arr) // 右子树(递归)
            } 
            return arr // 返回排好序的当前递归的节点
        };
      
      • 通过迭代方法来进行二叉树的前序遍历
        var preorderTraversal = function(root) {
            let result = [] // 定义排序数组
            let stack = [] // 定义栈
            let cur = root // 指定当前节点
            while(cur || stack.length > 0) { //  当前节点为空 或 栈为空时,循环结束
                while(cur) {
                    result.push(cur.val) // 根的值
                    stack.push(cur) // 当前节点入栈
                    cur = cur.left // 指定左子树为下一次的循环的根结点
                }
                cur = stack.pop() // 弹出栈
                cur = cur.right // 指定当前节点为右节点
            }
            return result // 返回最终的二叉树前序遍历的结果
        };
      
    • 中序遍历 【 左 + 根 + 右 】
      • 通过递归方法来进行二叉树的中序遍历
      var inorderTraversal = function(root, arr = []) {
          if (root) {
              inorderTraversal(root.left, arr) // 左子树(递归)
              arr.push(root.val) // 根
              inorderTraversal(root.right, arr) // 右子树(递归)
          }
          return arr // 返回当前节点
      };
      
      • 通过迭代方法来进行二叉树的中序遍历
        var preorderTraversal = function(root) {
            let result = [] // 定义排序数组
            let stack = [] // 定义栈
            let cur = root
            while(cur || stack.length > 0) {
                while(cur) { // 左
                    result.push(cur.val) 
                    stack.push(cur)
                    cur = cur.left
                }
                cur = stack.pop() // 弹出栈
                cur = cur.right // 右
            }
            return result
        };
      
    • 后序遍历 【 左 + 右 + 根 】
      • 同样可以用递归和迭代两种方法来进行排序
  • 广度遍历
    • 层序遍历 【 逐层 】
      • 处理完一层再去处理下一层的数据

二叉树的性质和遍历方法,都是非常重要的,希望在算法方面有所发展的小伙伴一定要好好掌握呦,很多复杂的数据结构都是通过对二叉树的各种排序操作得来的。千万不要觉得它很简单,就不忽略呦!!!