跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

AVL 树原理及 C++ 代码实现

AVL 树是一种自平衡二叉搜索树,核心特性是左右子树高度差绝对值不超过 1。通过 LL、RR、LR、RL 四种旋转操作维护平衡,确保插入、删除、查找的时间复杂度为 O(log n)。详细阐述了 AVL 树的理论原理,包括失衡判断与旋转策略,并提供了基于 C++ 模板的完整实现代码,涵盖节点定义、高度更新、旋转逻辑以及插入和删除操作的平衡处理。

草莓泡芙发布于 2026/3/29更新于 2026/9/870 浏览

1. 理论

AVL 树是由 Adelson-Velsky 和 Landis 提出的自平衡二叉搜索树,核心特性是左右子树的高度差(平衡因子)绝对值不超过 1(平衡因子 = 左子树高度 - 右子树高度)。它继承了二叉搜索树'左子树节点值 < 根节点值 < 右子树节点值'的排序特性,同时通过旋转操作(LL、RR、LR、RL 四种类型)解决普通二叉搜索树可能退化为链表的问题,确保树的高度始终维持在 O(log n) 级别。因此,AVL 树的插入、删除、查找操作时间复杂度均为 O(log n),适用于需要高效动态维护有序数据的场景。

在 BST 树中如果按顺序插入元素,树可能会退化为链表,导致时间复杂度从 O(log n) 变为 O(n)。AVL 树为了维护节点平衡引入了四个节点的旋转操作。

1.1 左孩子左子树太高了(右旋 LL)

当某个节点的左孩子的左子树过高时,需要进行右旋。以失衡节点为轴旋转,将左孩子提升为新的根节点。

伪代码:

child = node->left;
node->left = child->right;
child->right = node;

同时需要更新 node 和 child 节点的高度值。

1.2 右孩子的右子树太高了(左旋 RR)

当某个节点的右孩子的右子树过高时,需要进行左旋。同理,将右孩子提升为新的根节点,原根节点变为左孩子。

伪代码:

child = node->right;
node->right = child->left;
child->left = node;

1.3 左孩子的右子树太高了(LR)

当左孩子的右子树过高时,无法通过一次旋转完成平衡。解决方案是先对左孩子进行一次左旋,将其转化为 LL 情况,然后再对当前节点进行一次右旋。

伪代码:

left_rotate(child);
right_rotate(node);

1.4 右孩子的左子树太高了(RL)

当右孩子的左子树过高时,先对右孩子进行一次右旋,转化为 RR 情况,然后再对当前节点进行一次左旋。

伪代码:

right_rotate(child);
left_rotate(node);

2. 代码实现

2.1 框架搭建

使用 C++ 模板类实现 AVL 树,包含节点定义、高度管理、旋转操作及插入删除逻辑。

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;

template<typename T, typename Comp = less<T>>
class AvlTree {
private:
     Node {
        (T data) : (data), (), (), () {}
        T value;
        Node* left;
        Node* right;
         height;
    };

    Node* root;
    Comp compare;
    queue<Node*> q;

    {
         (node == )  ;
          node->height;
    }

    {
        node->height = ((node->left), (node->right)) + ;
    }

    {
        Node* child = node->right;
        node->right = child->left;
        child->left = node;
        (node);
        (child);
         child;
    }

    {
        Node* child = node->left;
        node->left = child->right;
        child->right = node;
        (node);
        (child);
         child;
    }

    {
        node->left = (node->left);
         (node);
    }

    {
        node->right = (node->right);
         (node);
    }

    {
         (node == )   (val);
         (val == node->value)  node;
          ((node->value, val)) {
            node->right = (node->right, val);
             ((node->right) - (node->left) > ) {
                Node* child = node->right;
                 ((child->left) > (child->right)) {
                    node = (node);
                }  {
                    node = (node);
                }
            }
        }   ((val, node->value)) {
            node->left = (node->left, val);
             ((node->left) - (node->right) > ) {
                Node* child = node->left;
                 ((child->left) > (child->right)) {
                    node = (node);
                }  {
                    node = (node);
                }
            }
        }
        (node);
         node;
    }

    {
         (node == )  ;
         (node->value == val) {
             (node->right ==  && node->left == ) {
                 node;
                 ;
            }   (node->left ==  && node->right != ) {
                Node* child = node->right;
                 node;
                 child;
            }   (node->left !=  && node->right == ) {
                Node* child = node->left;
                 node;
                 child;
            }  {
                 ((node->left) >= (node->right)) {
                    Node* pre = node->left;
                     (pre->right != ) pre = pre->right;
                    T data = pre->value;
                    node->value = data;
                    node->left = (node->left, pre->value);
                }  {
                    Node* rear = node->right;
                     (rear->left != ) rear = rear->left;
                    node->value = rear->value;
                    node->right = (node->right, rear->value);
                }
            }
        }   ((node->value, val)) {
            node->right = (node->right, val);
        }   ((val, node->value)) {
            node->left = (node->left, val);
        }

         ((node->left) - (node->right) > ) {
            Node* child = node->left;
             ((child->left) > (child->right)) {
                node = (node);
            }  {
                node = (node);
            }
        }   ((node->right) - (node->left) > ) {
            Node* child = node->right;
             ((child->left) > (child->right)) {
                node = (node);
            }  {
                node = (node);
            }
        }
        (node);
         node;
    }

    {
         (node == ) ;
        cout << node->value << ;
        (node->left);
        (node->right);
    }

:
    () : () {}

    {
        root = (root, val);
    }

    {
        root = (root, val);
    }

    {
        (root);
        cout << endl;
    }

    {
        q.(root);
         (!q.()) {
             length = q.();
             ( i = ; i <= length; i++) {
                Node* cur = q.();
                q.();
                cout << cur->value << ;
                 (cur->left != ) q.(cur->left);
                 (cur->right != ) q.(cur->right);
            }
            cout << endl;
        }
        cout << endl;
    }
};

{
    AvlTree<> p;
     ( i = ; i <= ; i++) {
        p.(i);
    }
    p.();
    cout <<  << ;
    p.();
    cout <<  << endl;
    p.();
     ;
}
struct
Node
value
left
nullptr
right
nullptr
height
1
int
int getHeight(Node* node)
if
nullptr
return
0
else
return
void setHeight(Node* node)
max
getHeight
getHeight
1
Node* leftRotate(Node* node)
setHeight
setHeight
return
Node* rightRotate(Node* node)
setHeight
setHeight
return
Node* LR(Node* node)
leftRotate
return
rightRotate
Node* RL(Node* node)
rightRotate
return
leftRotate
Node* Pinsert(Node* node, T val)
if
nullptr
return
new
Node
if
return
else
if
compare
Pinsert
if
getHeight
getHeight
1
if
getHeight
getHeight
RL
else
leftRotate
else
if
compare
Pinsert
if
getHeight
getHeight
1
if
getHeight
getHeight
rightRotate
else
LR
setHeight
return
Node* Premove(Node* node, T val)
if
nullptr
return
nullptr
if
if
nullptr
nullptr
delete
return
nullptr
else
if
nullptr
nullptr
delete
return
else
if
nullptr
nullptr
delete
return
else
if
getHeight
getHeight
while
nullptr
Premove
else
while
nullptr
Premove
else
if
compare
Premove
else
if
compare
Premove
if
getHeight
getHeight
1
if
getHeight
getHeight
rightRotate
else
LR
else
if
getHeight
getHeight
1
if
getHeight
getHeight
RL
else
leftRotate
setHeight
return
void ShowDFS(Node* node)
if
nullptr
return
" "
ShowDFS
ShowDFS
public
AvlTree
root
nullptr
void Insert(T val)
Pinsert
void Remove(T val)
Premove
void Show()
ShowDFS
void ShowBFS()
push
while
empty
int
size
for
int
1
front
pop
" "
if
nullptr
push
if
nullptr
push
int main()
int
for
int
1
10
Insert
Remove
4
"广搜"
'\n'
ShowBFS
"前序"
Show
return
0

目录

  1. 1. 理论
  2. 1.1 左孩子左子树太高了(右旋 LL)
  3. 1.2 右孩子的右子树太高了(左旋 RR)
  4. 1.3 左孩子的右子树太高了(LR)
  5. 1.4 右孩子的左子树太高了(RL)
  6. 2. 代码实现
  7. 2.1 框架搭建

更多推荐文章

查看全部
  • Spring Cloud Nacos 服务注册与配置中心实战
  • 使用 Python 和 PyQt6 开发简易记事本
  • Llama-Factory 训练进度条卡死排查与优化指南
  • Qclaw 使用教程:基于微信的 AI 智能体操作指南
  • 前端请求后端返回 404/405/500 状态码:完整排查与解决指南
  • 网络安全行业人才缺口与薪资水平深度解析
  • 5 个适用于生活与工作的 Python 自动化项目
  • Python + Bright Data MCP 实时抓取 Google 搜索结果实战
  • Python AI 大模型部署指南:本地运行、API 服务与 Docker 封装
  • C++ 技术面试常见问题解析(三)
  • 机器人架构搭建核心准则:先论文论证,后工程落地
  • Fooocus 部署实践:本地手动配置与云平台一键启用对比
  • GLM-4.5-Air-Base 开源:1060 亿参数智能推理模型免费商用
  • 二分答案专题实战:木材加工与砍树问题详解
  • Rust 语言的前世今生与核心技术解析
  • Meta:BackTranslation 与 IBM Self Alignment 技术解析
  • Llama Factory 微调:如何选择最佳超参数
  • 硕士论文盲审前如何降低 AI 检测率及评委关注点分析
  • OpenClaw 配置飞书机器人教程
  • ComfyUI-Manager 插件管理工具使用指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online