红黑树

【树形结构】红黑树 {概念及性质;红黑树的结构;带头结点的红黑树;红黑树的实现;红黑树插入操作详细解释;红黑树的验证} 阅读详情

当我们在使用二叉搜索树时,如果树的高度较高,对其的操作并不比对链表操作要快。原因是二叉搜索树在插入顺序基本有序时会退化为一个排序链表,所以说是不平衡的。

对二叉搜索树的改进有AVL树和红黑树。先来看红黑树,它广泛应用在STL的set和map,Java库和Linux内核等中 。

红黑树是一颗平衡的二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是RED或BLANK。通过对任何一条从根节点到叶子节点的简单路径上各个节点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是近似平衡的。

红黑树的约束如下:

  • 每个节点要么是红色的,要么是黑色的;
  • 根节点是黑色的;
  • 如果一个节点是红色的,那么它的两个子节点都是黑色的;
  • 对每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含数目相同的黑色节点;
  • 每个叶子节点是黑色的(这里的叶子节点指的是NIL节点,即空节点)。

红黑树的插入操作步骤如下:

  • 先按照搜索树的步骤将节点插入到相应位置,并置该节点颜色为红色。设该节点指针为cur;
  • 如果破坏了以上某些条件,则对该树进行相应的调整,步骤如下:
    • 情况1:若cur的父亲结点和叔叔节点都为红色,则进行红色提升;
    • 情况2:若父红叔黑或叔叔不存在,且cur为其父节点的右孩子,则令cur=parent并以父节点为根进行旋转;
    • 情况3:若父红叔黑或叔叔不存在,且cur为其父节点的左孩子,则将父节点变为黑色,祖父节点变为红色并以祖父节点为根进行旋转;

代码如下:


#pragma once

#include<iostream>
using namespace std;

enum Color
{
    RED,
    BLANK,
};

template<typename K,typename V>
struct RBTreeNode{
    K _key;
    V _value;

    RBTreeNode<K,V>* _left;
    RBTreeNode<K,V>* _right;
    RBTreeNode<K,V>* _parent;

    Color _color;

    RBTreeNode(const K& key=K(),const V& value=V())
        :_key(key),_value(value)
         ,_left(NULL),_right(NULL)
         ,_parent(NULL)
         ,_color(RED)
    {}
};

template<typename K,typename V>
class RBTree{
    typedef RBTreeNode<K,V> Node;
public:
    RBTree()
        :_root(nil)
    {}
    bool Insert(const K& key,const V& value)
    {
        Node* s=new Node(key,value);
        Node* parent=nil;
        Node* cur=_root;
        while(cur!=nil)
        {
            parent=cur;
            if(cur->_key>cur->_key)
                cur=cur->_left;
            else
                cur=cur->_right;
        }
        cur->_parent=parent;
        if(parent==nil)
            _root=s;
        else if(s->_key>parent->_key)
            parent->_right=s;
        else 
            parent->_left=s;
        s->_left=s->_right=nil;
        //s->_color=RED;
        RB_INSERT_FIX(s);
    }
    bool Remove(const K& key);
    Node* Find(const K& key);
    bool IsBalance();
protected:
    void RotateL(Node* root)
    {
        if(root==NULL)
            return;
        Node* parent=root;
        Node* subR=parent->_right;
        Node* subRL=subR->_left;
        parent->_right=subRL;
        if(subRL!=NULL)
            subRL->_parent=parent;
        Node* ppNode=parent->_parent;
        subR->_left=parent;
        parent->_parent=subR;
        if(ppNode!=NULL)
        {
            if(ppNode->_left==parent)
                ppNode->_left=subR;
            else
                ppNode->_right=subR;
        }
        else
        {
            _root=subR;
        }
        subR->_parent=ppNode;
        parent->_bf = subR->_bf = 0;
    }
    void RotateR(Node* root)
    {
        if(root==NULL)
            return;
        Node* parent=root;
        Node* subL=parent->_left;
        Node* subLR=subL->_right;
        parent->_left=subLR;
        if(subLR!=NULL)
            subLR->_parent=parent;
        Node* ppNode=parent->_parent;
        subL->_right=parent;
        parent->_parent=subL;
        if(ppNode!=NULL)
        {
            if(ppNode->_left==parent)
                ppNode->_left=subL;
            else
                ppNode->_right=subL;
        }
        else
        {
            _root=subL;
        }
        subL->_parent=ppNode;
        parent->_bf = subL->_bf = 0;
    }
    void RB_INSERT_FIX(Node* cur)
    {
        while(cur->_parent._color==RED)
        {
            Node* parent=cur->_parent;
            Node* grandfather=parent->_parent;
            Node* uncle;
            if(parent=grandfather->_left)
            {
                uncle=grandfather->_right;
                if(uncle->_color=RED)
                {
                    parent->_color=BLANK;
                    uncle->_color=BLANK;
                    grandfather->_color=RED;
                    cur=grandfather;
                }
                else if(cur=parent->_right)
                {
                    cur=parent;
                    rotateL(cur);
                }
                else
                {
                    parent->_color=BLANK;
                    grandfather->_color=RED;
                    rotateR(grandfather);
                }
            }
            else
            {
                uncle=grandfather->_left;
                if(uncle->_color=RED)
                {
                    parent->_color=BLANK;
                    uncle->_color=BLANK;
                    grandfather->_color=RED;
                    cur=grandfather;
                }
                else if(cur=parent->_left)
                {
                    cur=parent;
                    rotateR(cur);
                }
                else
                {
                    parent->_color=BLANK;
                    grandfather->_color=RED;
                    rotateL(grandfather);
                }
            }
        }
        _root->_color=BLANK;
    }
private:
    Node* _root;
    static Node* nil;
};

template<typename K,typename V>
RBTreeNode<K,V>* RBTree<K,V>::nil=new RBTreeNode<K,V>();

以上

如果你有任何想法或是可以改进的地方,欢迎和我交流!

完整代码在github上:点我前往

本文首发于www.sbrave.cn
【完】

个人关于红黑树的理解 目录   红黑树(red-black-tree) 一.红黑树的定义和性质 二.红黑树的结构 三.输出一颗红黑树 四.查询红黑树 查找 查找最大关键字元素和最小关键字元素 查找前驱和后继 五.※插入和删除 插入 删除 六.完整代码 红黑树(red-black-tree) 一.红黑树的定义和性质 红黑树是一种二叉查找树,在每个结点上增加一个存储位表示结点的颜色,,可以是... 阅读详情

相关推荐

红黑树解析

写在前面:我是「且听风吟」,目前是某上市游戏公司的大数据开发工程师,热爱大数据开源技术,喜欢分享自己的所学所悟,现阶段正在从头梳理大数据体系的知识,以后将会把时间重点放在Spark和Flink上面。 如果你也对大数据感兴趣,希望在这个行业一展拳脚。欢迎关注我,我们一起努力,一起学习。博客地址:https://ropledata.blog.youkuaiyun.com 博客的名字来源于:且听风吟,静待花开。也符合我对技术的看法,想要真正掌握一门技术就需要厚积薄发的毅力,同时保持乐观的心态。 你只管努力,剩下的交给.

静待花开 2229

红黑树详解,对插入旋转独到理解

R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。 将一个节点插入到红黑树中,需要执行哪些步骤呢?首先,将红黑树当作一颗二叉查找树,将节点插入;然后,将节点着色为红色;最后,通过旋转和重新着色等方法来修正该树,使之重新成为一颗红黑树。详细描述如下: 第一步: 将红黑树当作一颗二叉查找树,将节点插入。 红黑树本身就是一颗二叉查找树,将节点插入后,该树仍然是一颗二叉...

Allence的博客 2751

保姆级避坑指南:在NVMe SSD上安装Ubuntu 24.04,搞定RST错误和分区方案

本文提供在NVMe SSD上安装Ubuntu 24.04的详细指南,解决RST错误和分区方案问题。从BIOS设置到分区策略优化,帮助用户充分发挥NVMe固态硬盘性能,避免常见安装陷阱,实现无痛安装和后期调优。

weixin_26976635的博客 560

数据结构-红黑树

红黑树的结构特性红黑树也是搜索树的一种,是一种弱平衡二叉树,它的出现是为了,因为 AVL 树对平衡性要求很高,所以插入和删除都需要进行平衡处理。而红黑树加入了节点颜色标志,可以减少这种强平衡要求,在一些需要频繁插入和删除的结构中经常使用。例如,C++的 STL 中的set,map,以及 linux 的虚拟内存管理都是通过红黑树去实现的。红黑树的结构特性红黑树的时间复杂度为 O(lgn)红黑树的结构定义1.红,BLACK = 1黑2.3.RED = 0;5.

jiu_yue_ya的博客 234

MATLAB实战:手把手教你搭建构网逆变器同步稳定性仿真模型(附避坑指南)

本文详细介绍了如何在MATLAB/Simulink平台上搭建构网逆变器同步稳定性仿真模型,涵盖从基础模块配置到虚拟同步机控制实现的完整流程。针对电力电子工程师常见的控制参数整定困难、仿真结果偏差等问题,提供了LCL滤波器谐振抑制、虚拟惯量优化等关键技术解决方案,并附有避坑指南和工程实践技巧,助力研究者高效完成仿真建模。

weixin_29051193的博客 297

AR Tag 与 ROS:从基础部署到机器人视觉定位实战

本文详细介绍了AR Tag技术在ROS环境下的部署与应用,涵盖从基础原理到机器人视觉定位的实战技巧。通过分析AR Tag的特征提取、位姿解算等核心技术,结合ROS工具包`ar_track_alvar`的配置优化,帮助开发者实现高精度的视觉定位系统。文章还分享了深度相机配置、坐标转换及性能优化等实用经验,适用于仓储机器人、物流分拣等场景。

weixin_33146151的博客 181

查找树-- Red Black Tree 【红黑树】原理图解及示例代码

红黑树 概念 红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组 红黑树是一种特化的AVL树(自平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。但红黑树的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但对之进行平衡的代价较低, 其平均统计性能要强于 AVL Tree。 红黑树的插入删除比AVL树更便于控制操作,整体性能略优于AVL树 查找时不需要使用颜色信

penriver的博客 722

Pwntools不只是PWN:用它写个自动化Fuzz脚本,挖掘Linux命令行工具漏洞

本文探讨了如何利用Pwntools构建自动化Fuzz脚本,挖掘Linux命令行工具中的漏洞。通过详细的代码示例和实战案例,展示了Pwntools在Fuzzing中的高效性和灵活性,特别适合快速验证特定场景的安全问题。文章还提供了进阶技巧和避坑指南,帮助安全研究人员快速上手并提升测试效率。

weixin_28718345的博客 221

红黑树介绍

红黑树一、红黑树的概念红黑树的性质红黑树节点的定义红黑树结构二、使用步骤1.引入库2.读入数据总结 一、红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。 红黑树的性质 每个结点不是红色就是黑色 根节点是黑色的 如果一个节点是红色的,则它的两个孩子结点是黑色的 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数

mz474920631的博客 4万+

eNSP-抓包解析TCP三次握手和四次挥手的过程

一、环境搭建 1.设备连接 2.服务器配置 3.客服端配置 二、抓包测试 1.打开抓包软件 2.客户端获取数据 三、抓包结果

小橙子的博客 3351

【WRF-UCM】BEP+BEM 模拟:README

【WRF-UCM】BEP+BEM 模拟:README

WW、forever的博客 223

【C++】红黑树

因为每个节点都存在颜色,并且不为黑色就为红色,所以我们可以定义一个表示颜色的枚举常量。红黑树依旧是三叉链。

bushibrnxiaohaij的博客 2963

【AI智能体】Codex 浏览器操作自动化任务实战操作详解

【AI智能体】Codex 浏览器操作自动化任务实战操作详解

congge 4105

红黑树原理详解

   二叉查找树由于在频繁的动态更新过程中,可能会出现树的高度远大于 log2n的情况,所以就会导致各个操作效率下降,最坏的情况下就会退化为链表,变为O(n).很明显,想要解决这个问题,有效的一种办法就是使得树的高度不要差很多,也就是平衡它.     最先发明的平衡二叉查找树是AVL树,(它严格符合平衡二叉查找树的定义,即任何节点的左右子树高度相差不超过 1,是一种高度平衡的二叉查找树。)但是在...

Tattoo的博客 3万+

华为OD机试 - 直捣黄龙 - 广度优先搜索BFS(Python/JS/C/C++ 新系统 200分)

从样例 1 可知:5 / 2,2 -> 输出 2 9如果按“移动步数”计算应该是 8,但题目输出是 9,说明这里的“路径长度”统计的是 路径上经过的节点数量。最短路径条数:ways[end]路径长度:dist[end] + 1。

学Java,找哪吒 125

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【C++】————红黑树

RED,BLACK, _kv(kv){}private:_left、_right 和 _parent 分别指向节点的左子节点、右子节点和父节点。_kv 是一个 pair,存储节点的键和值。_col 表示节点的颜色,可以是 RED 或 BLACK。接收一个 pair 作为参数,初始化节点的键值对,并将节点的颜色初始化为 RED。其他指针成员初始化为 nullptr。

bhbcdxb123的博客 2166

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

C++——红黑树

C++之红黑树板块讲解

dongxue727504的博客 3277

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【C++】——红黑树(手撕红黑树,彻底弄懂红黑树)

我们之前都学过ALV树,AVL树的本质就是一颗平衡二叉树,它的作用就是查找,插入和删除节点,最坏的时间复杂度都是O(logn)的,同时维护的高度差都是小于等于1的,但是也就是因为这个原因才被红黑树所替代红黑树是一种自平衡的二叉查找树,是一种高效的查找树。它是由 Rudolf Bayer 于1978年发明,在当时被称为平衡二叉 B 树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的红黑树。

m0_74092462的博客 2084

红黑树系列1——红黑树的建立

原创码字不易,转载请注明出处,谢谢~ 红黑树系列2——红黑树的删除(码字中,待发表) 红黑树系列3——红黑树的应用(码字中,待发表) 红黑树系列4——红黑树的代码实现(码代码中,待发表) 红黑树动态建立,删除网站(强强强强烈推荐,根据网页上自己构建和删除几遍红黑树,比看文章有用太多太多):https://www.cs.usfca.edu/~galles/visualization/RedBlack.html 目录 一、红黑树的建立 1、建立红黑树 例子1、解决连续右右红色节点 例子2、解决

Bob的博客 2831

C++中红黑树的实现 -- 红黑树的概念,红黑树的规则,红黑树插入时的情况分析,红黑树的实现,红黑树的查找,红黑树的验证

红黑树是一种自平衡二叉搜索树,通过颜色约束确保最长路径不超过最短路径的两倍。其核心规则包括:根节点为黑色、红色节点不能连续、每条路径黑色节点数相同。插入操作涉及变色和旋转两种调整方式,根据叔叔节点颜色分为不同处理情况。与AVL树相比,红黑树平衡要求较宽松,旋转次数更少,但查找效率相近(O(logN))。本文详细介绍了红黑树的结构定义、插入逻辑(包括单旋和双旋场景)、验证方法,并提供了与AVL树的性能对比测试代码,显示两者在百万级数据下的操作耗时相当。

CSQCSQCC的博客 1614

【红黑树】都这样讲了,不会还有人不会红黑树吧

我们在前面学习过二叉树,而二叉树有被简单的分为普通二叉树,二叉搜索树,完全二叉树,二叉平衡树等,在二叉搜索树中包含有 AVL树,红黑树。博主在以前的文章中写过AVL树的相关内容,有兴趣的读者可以去康康,直接甩链接(124条消息) 【数据结构高阶】终于有人把AVL树给说清了_小小怪下士~的博客-优快云博客我们学习过AVL树的同学们都知道,AVL树是一个绝对平衡的二叉树,所谓的绝对平衡说的就是一个节点的左右子树的高度之差的绝对值是不能超过1的,我们同时也知道这个。

qq_54883034的博客 4122
上一篇: B树
下一篇: KMP算法
SmartBrave
博客等级 码龄12年 25粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值