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

C++ 红黑树插入与平衡调整详解

红黑树是一种自平衡二叉搜索树,通过颜色标记和旋转操作维持近似平衡。红黑树的五条性质,重点讲解了插入新节点后的颜色调整策略。当父节点为红色时,根据叔叔节点的颜色分为变色和旋转两种情况,确保满足红黑树性质。最后提供了判断红黑树是否平衡的递归检查方法。

筑梦师发布于 2026/2/6更新于 2026/9/1067 浏览
C++ 红黑树插入与平衡调整详解

前言

红黑树是二叉搜索树的一种变体,基于红黑树实现的结构包括 map 和 set。它是一种近似平衡的二叉搜索树,通过引入颜色属性来判断简单路径的长度,从而达到平衡的目的。

红黑树引入了以下规则:

  1. 节点不是红色就是黑色。
  2. 根节点是黑色的。
  3. 不存在连续的两个红色节点。
  4. 每条简单路径上的黑色节点数目应该相同。

只要满足以上条件,最短路径长度不超过最长路径的两倍。本文将着重介绍插入部分的调整以及判断整个树是否满足红黑树的条件。

节点定义

红黑树有颜色属性,使用枚举表示 RED 和 BLACK。采用三叉链结构,包含 parent 指针。使用 key-value 结构存储数据。

enum Colour { BLACK, RED };

template<class T, class V>
struct RBTreeNode {
    RBTreeNode<T, V>* _left;
    RBTreeNode<T, V>* _right;
    RBTreeNode<T, V>* _parent;
    Colour _col;
    pair<T, V> _kv;

    RBTreeNode(const pair<T,V>& kv) :_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _col(RED) {}
};

初始化为红色是为了方便插入调整。整体红黑树类结构与 AVL 树类似。

template<class T,class V>
class RBTree {
public:
    typedef RBTreeNode<T, V> Node;
private:
    Node* _root = nullptr;
};

插入部分

插入逻辑与二叉搜索树类似,区别在于插入后需要调整颜色。如果插入的是根节点,颜色必须设为黑色。

插入流程

  1. 查找位置:按照二叉搜索树规则找到插入位置。
  2. 连接节点:将新节点连接到父节点下,新节点默认颜色为红色。
  3. 颜色调整:检查是否违反红黑树性质,若违反则进行变色或旋转。
bool Insert(const pair<T, V>& kv) {
    if (_root == nullptr) {
        _root = new Node(kv);
        _root->_col = BLACK;
        return true;
    }

    Node* root = _root;
    Node* parent = nullptr;

    // 查找插入位置
    while (root) {
        if (kv.first > root->_kv.first) {
            parent = root;
            root = root->_right;
        } else if (kv.first < root->_kv.first) {
            parent = root;
            root = root->_left;
        } else {
            return false; // 已存在
        }
    }

    Node* cur = new Node(kv);
    
    // 连接节点
    if (parent->_kv.first > kv.first) {
        parent->_left = cur;
    } else {
        parent->_right = cur;
    }
    cur->_parent = parent;

    // 颜色调整
    while (parent && parent->_col == RED) {
        Node* grandfather = parent->_parent;
        
        // 父节点在左边
        if (parent == grandfather->_left) {
            Node* uncle = grandfather->_right;
            
            // 情况一:叔叔节点存在且为红色
            if (uncle && uncle->_col == RED) {
                parent->_col = uncle->_col = BLACK;
                grandfather->_col = RED;
                cur = grandfather;
                parent = grandfather->_parent;
            } 
            // 情况二:叔叔节点不存在或为黑色
            else {
                // 单旋(左左)
                if (cur == parent->_left) {
                    RotateR(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                } 
                // 双旋(左右)
                else {
                    RotateL(parent);
                    RotateR(grandfather);
                    cur->_col = BLACK;
                    grandfather->_col = RED;
                }
                break;
            }
        } 
        // 父节点在右边
        else {
            Node* uncle = grandfather->_left;
            
            // 情况一:叔叔节点存在且为红色
            if (uncle && uncle->_col == RED) {
                parent->_col = uncle->_col = BLACK;
                grandfather->_col = RED;
                cur = grandfather;
                parent = grandfather->_parent;
            } 
            // 情况二:叔叔节点不存在或为黑色
            else {
                // 单旋(右右)
                if (cur == parent->_right) {
                    RotateL(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                } 
                // 双旋(右左)
                else {
                    RotateR(parent);
                    RotateL(grandfather);
                    cur->_col = BLACK;
                    grandfather->_col = RED;
                }
                break;
            }
        }
    }
    
    _root->_col = BLACK;
    return true;
}

判断部分

判断红黑树是否达标,主要检查四条规则。根节点必须为黑色。检查是否存在连续红色节点。检查每条路径黑色节点数是否一致。

bool IsBalance() {
    if (_root == nullptr || _root->_col == RED) {
        return false;
    }

    int base = 0;
    Node* cur = _root;
    while (cur) {
        if (cur->_col == BLACK) {
            base++;
        }
        cur = cur->_left;
    }
    return Check(_root, 0, base);
}

private:
bool Check(Node* root, int blackNum, const int base) {
    if (root == nullptr) {
        if (base != blackNum) {
            return false;
        }
        return true;
    }

    if (root->_col == RED && root->_parent->_col == RED) {
        return false;
    }

    if (root->_col == BLACK) {
        blackNum++;
    }

    return Check(root->_left, blackNum, base) && Check(root->_right, blackNum, base);
}

相对于 AVL 树来说,红黑树在保持平衡的同时减少了旋转次数,性能通常更优。

目录

  1. 前言
  2. 节点定义
  3. 插入部分
  4. 插入流程
  5. 判断部分

更多推荐文章

查看全部
  • Python 3.14.2 Windows 安装指南
  • 2026 年前端跨端框架选型指南:Flutter、RN 与 uni-app 深度对比
  • 基于大模型的 Web UI 自动化方案对比与选型
  • 自然语言处理(NLP)在法律领域的应用与实战
  • AI 核心概念速通教程
  • 主流大模型降英文 AI 检测率横向测评:千问、DeepSeek、KIMI 等对比
  • Android WebView 内核升级方案详解
  • 字节跳动前端一面面试真题与深度解析
  • Flutter pathfinding 库的 OpenHarmony 适配实战
  • Windows 环境 AI 绘画工具网络代理冲突及 JSON 报错解决
  • MusePublic Art Studio 镜像部署:免配置运行 SDXL 绘画
  • 贪心算法实战:柠檬水找零、数组减半与最大数拼接
  • 机器人灵巧手:技术演进、市场格局与未来前景
  • 基于 Python + Django 的大学生自习室预约系统
  • 昇腾 910B 部署 Llama-2-7b 深度测评与实战指南
  • Spring 核心面试题:Bean 生命周期、AOP 与事务管理
  • Spring AI 1.1.2 集成 MCP(Model Context Protocol)实战:以 Tavily 搜索为例
  • Java Web 开发环境搭建:IDEA 与 Tomcat 配置指南
  • 法奥机器人 ROS2 环境搭建
  • 机器人具身智能:核心定义、指标与标准体系

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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