Maoyl's blog Maoyl's blog
首页
  • 前端基础

    • HTML
    • CSS
    • CSS动画
    • JavaScript文章
    • stylus
  • 性能优化

    • 《性能优化》笔记
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《JavaScript设计模式》笔记
    • 《TypeScript 从零实现 axios》
    • TypeScript笔记
    • JS设计模式总结笔记
  • 前端框架

    • Vue相关
    • React相关
  • 前端监控

    • 前端监控简介
  • 学习笔记

    • 《Vue》笔记
    • 《React》笔记
    • 小程序学习笔记
  • 后端基础

    • Nodejs
  • 学习笔记

    • 数据结构
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • 网页性能
  • 学习笔记

    • 《Git》学习笔记
    • 《Vim》学习笔记
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

maoyln

日日行,不怕千万里
首页
  • 前端基础

    • HTML
    • CSS
    • CSS动画
    • JavaScript文章
    • stylus
  • 性能优化

    • 《性能优化》笔记
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《JavaScript设计模式》笔记
    • 《TypeScript 从零实现 axios》
    • TypeScript笔记
    • JS设计模式总结笔记
  • 前端框架

    • Vue相关
    • React相关
  • 前端监控

    • 前端监控简介
  • 学习笔记

    • 《Vue》笔记
    • 《React》笔记
    • 小程序学习笔记
  • 后端基础

    • Nodejs
  • 学习笔记

    • 数据结构
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • 网页性能
  • 学习笔记

    • 《Git》学习笔记
    • 《Vim》学习笔记
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 第一讲 基本概念

  • 第二讲 线性结构

  • 第三讲 树(上)

  • 第四讲 树(中)

    • 二叉搜索树
    • 平衡二叉树
      • 二叉树平衡
      • 平衡二叉树
      • 平衡二叉树的调整
        • 示例代码
      • 总结
  • 第五讲 树(下)

  • 第六讲 图(上)

  • 《数据结构》学习笔记
  • 第四讲 树(中)
maoyln
2024-07-09
目录

平衡二叉树

# 二叉树平衡

二叉平衡树(Balanced Binary Tree),又称为AVL树,是一种自平衡的二叉搜索树。在二叉平衡树中,任何节点的两个子树的高度最大差别不超过1,这样既保证了快速查找的时间复杂度(O(log n)),也避免了树的高度退化为链表。

# 平衡二叉树

平衡二叉树(Balanced Binary Search Tree, BBST)是指满足某种平衡条件的二叉搜索树,例如AVL树、红黑树等。这些树的平衡性保证了它们在插入和删除操作后的性能不会急剧下降。

# 平衡二叉树的调整

当进行插入或删除操作导致树失去平衡时,需要通过旋转来重新平衡树。常见的旋转有四种:左旋、右旋、左-右旋和右-左旋。

# 示例代码

# 定义一个树节点类,包含键值、左右子节点和高度属性

class TreeNode {
  constructor(key) {
      this.key = key; // 键值
      this.left = null; // 左子节点
      this.right = null; // 右子节点
      this.height = 1; // 初始高度设为1
  }
}
1
2
3
4
5
6
7
8

# 定义一个AVL树类,用于管理树结构

class AVLTree {
  constructor() {
      this.root = null; // 初始化树的根节点为空
  }

  // 获取节点的高度
  getHeight(node) {
      if (node === null) return 0; // 空节点高度为0
      return node.height;
  }

  // 计算节点的平衡因子
  getBalanceFactor(node) {
      if (node === null) return 0;
      return this.getHeight(node.left) - this.getHeight(node.right);
  }

  // 右旋操作,用于调整树的平衡
  rightRotate(y) {
      let x = y.left; // 获取y的左子节点
      let T2 = x.right; // 获取x的右子节点

      x.right = y; // 将y设置为x的右子节点
      y.left = T2; // 将T2设置为y的左子节点

      // 更新x和y的高度
      y.height = Math.max(this.getHeight(y.left), this.getHeight(y.right)) + 1;
      x.height = Math.max(this.getHeight(x.left), this.getHeight(x.right)) + 1;

      return x; // 返回新的根节点
  }

  // 左旋操作,与右旋类似
  leftRotate(x) {
      let y = x.right;
      let T2 = y.left;

      y.left = x;
      x.right = T2;

      x.height = Math.max(this.getHeight(x.left), this.getHeight(x.right)) + 1;
      y.height = Math.max(this.getHeight(y.left), this.getHeight(y.right)) + 1;

      return y;
  }

  // 插入新键值到树中
  insert(key) {
      this.root = this.insertNode(this.root, key);
  }

  // 递归地插入键值到树中,并调整树结构
  insertNode(node, key) {
      if (node === null) return new TreeNode(key); // 如果节点为空,则创建新节点并返回

      if (key < node.key) { // 插入左边
          node.left = this.insertNode(node.left, key);
      } else if (key > node.key) { // 插入右边
          node.right = this.insertNode(node.right, key);
      } else {
          return node; // 不允许插入重复键
      }

      // 更新节点的高度
      node.height = 1 + Math.max(this.getHeight(node.left), this.getHeight(node.right));

      // 获取平衡因子
      let balance = this.getBalanceFactor(node);

      // 根据平衡因子进行旋转调整
      // 左左情况
      if (balance > 1 && key < node.left.key) {
          return this.rightRotate(node);
      }
      // 右右情况
      if (balance < -1 && key > node.right.key) {
          return this.leftRotate(node);
      }
      // 左右情况
      if (balance > 1 && key > node.left.key) {
          node.left = this.leftRotate(node.left);
          return this.rightRotate(node);
      }
      // 右左情况
      if (balance < -1 && key < node.right.key) {
          node.right = this.rightRotate(node.right);
          return this.leftRotate(node);
      }

      return node; // 返回平衡后的节点
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

# 创建并使用AVL树实例

let avlTree = new AVLTree();
avlTree.insert(10);
avlTree.insert(20);
avlTree.insert(30);
avlTree.insert(40);
avlTree.insert(50);

console.log(avlTree);
1
2
3
4
5
6
7
8

# 上述结果的数据结构

AVLTree
{
    root: {
        key: 20,
        left: {
            key: 10,
            left: null,
            right: null,
            height: 1
        },
        right: {
            key: 40,
            left: {
                key: 30,
                left: null,
                right: null,
                height: 1
            },
            right: {
                key: 50,
                left: null,
                right: null,
                height: 1
            },
            height: 2
        },
        height: 3
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 数据结构可视化

# 总结

总结

  • 二叉平衡树 是一种自平衡的二叉搜索树,能够保证在插入和删除操作后树的结构保持相对平衡。
  • 平衡二叉树 概念更广,包括所有满足特定平衡条件的二叉搜索树。
  • 平衡二叉树的调整 是通过旋转操作来维护树的平衡,确保插入和删除操作后的时间复杂度仍为O(log n)。
  • AVL树 实现了严格的平衡条件,每一步插入或删除后都需要进行调整以保持平衡。
编辑 (opens new window)
#数据结构
上次更新: 2025/04/18, 01:42:12
二叉搜索树
堆

← 二叉搜索树 堆→

最近更新
01
GSAP动画库——如何高效写动画
04-17
02
自适应方案PxToRem
09-10
03
性能优化-requestAnimationFrame
08-10
更多文章>
Theme by Vdoing | Copyright © 2019-2025 备案号:京ICP备19058102号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式