【STL源码剖析】第五章 关联式容器 之 RB-tree(红黑树)

2024-08-22 13:08

本文主要是介绍【STL源码剖析】第五章 关联式容器 之 RB-tree(红黑树),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

RB-tree

[ 红黑树比AVL树的优势 ]( https://blog.csdn.net/mmshixing/article/details/51692892 )

RB-tree不仅是一个二叉搜索树,而且必须满足一些规则:

  1. 每个节点不是红色就是黑色(图中深色代表黑,浅色代表红)

  2. 根节点为黑色

  3. 如果节点为红,其子节点必须为黑

  4. 任一节点至NULL(树尾端)的任何路径,所含之黑节点数必须相同

根据规则4,新增节点不许为红;根据规则3,新增节点之父节点必须为黑。当新节点根据二叉搜索树的规则到达其插入点,却未能符合上述条件时,就必须调整颜色并旋转树形。

插入节点

在图5-13的RB-tree分别插入3,8,35,75,根据二叉搜索树的规则,这四个新节点落脚处应如图5-14所示,它们破坏了RB-tree的规则,因此必须调整树形,也就是旋转树形并改变节点颜色。

假设新节点为X,其父节点为P,祖父节点为G,伯父节点(父节点的兄弟节点)为S,曾祖父节点为GG

  • 状况1:S为黑且X为外侧插入。对此情况,先对P,G做一次单选转,再更改P,G颜色,即可重新满足红黑树的规则3。

  • 状况2:S为黑且X为内测插入。对此情况,必须现对P,X做一次单选转并更改G,X颜色,再将结果对G做一次单选转,即可再次满足红黑树规则3。

  • 状况3:S为红且X为外侧插入。对此情况,现对P和G做一次单选转,并改变X的颜色。此时如果GG为黑,一切搞定,但如果GG为红,则问题比较大,见状况4。

  • 状况4:S为红且X为外侧插入。对此情况,先对P和G做一次单选转,并改便X的颜色。此时如果GG也为红。害的持续网上做,直到不再有父子连续为红的情况。

一个自上而下的程序

为避免插入节点的情况4,可以用自顶向下的方法:假设新增节点为A,就顺着A的路径,当遇到一个节点X的两个儿子都为红,就将X改为红,两个儿子改为黑。当X的父节点也为红使用情况1或情况2中的方法做调整。

RB-tree的节点设计

RB-tree有红黑二色,并且拥有左右子节点,很容易勾勒出其结构风貌。下面是SGI STL的实现源码。为了有更大的弹性,节点分为两层。

由于RB-tree的各种操作时常需要上溯其父节点,所以特别在数据结构中安排了一个parent指针。

  typedef bool __rb_tree_color_type;  const __rb_tree_color_type __rb_tree_red = false;     // 红色为0  const __rb_tree_color_type __rb_tree_black = true; // 黑色为1    struct __rb_tree_node_base  {    typedef __rb_tree_color_type color_type;    typedef __rb_tree_node_base* base_ptr;      color_type color;     // 节点颜色,红色或黑色    base_ptr parent;      // 该指针指向其父节点    base_ptr left;        // 指向左节点    base_ptr right;       // 指向右节点      static base_ptr minimum(base_ptr x)    {       while (x->left != 0) x = x->left; //一直向左走,找到最小值       return x;                                }      static base_ptr maximum(base_ptr x)    {      while (x->right != 0) x = x->right; //一直向右走,找到最大值      return x;                               }  };    template <class Value>  struct __rb_tree_node : public __rb_tree_node_base  {    typedef __rb_tree_node<Value>* link_type;    Value value_field;   //节点值  }; 
RB-tree的迭代器

SGI将RB-tree迭代器实现分为两层。图5-16是两层节点结构和双层迭代器结构间的关系,其中主要意义是: _ rb_tree_node 继承自 rb_tree_node_base ,rb_tree_iterator继承自_rb_tree_base_iterator。

RB-tree的元素操作

RB-tree提供两种插入操作:insert_unique()和insert_equal(),前者标识被插入节点的键值(key)在整棵树中必须独一无二(因此,如果整棵树中已存在相同的键值,插入操作就不会真正进行),后者标识被插入节点的键值在整棵树中可以重复,因此,无论如何插入都会成功(除非空间不足导致配置失败)。



这篇关于【STL源码剖析】第五章 关联式容器 之 RB-tree(红黑树)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1096360

相关文章

Java JUC并发集合详解之线程安全容器完全攻略

《JavaJUC并发集合详解之线程安全容器完全攻略》Java通过java.util.concurrent(JUC)包提供了一整套线程安全的并发容器,它们不仅是简单的同步包装,更是基于精妙并发算法构建... 目录一、为什么需要JUC并发集合?二、核心并发集合分类与详解三、选型指南:如何选择合适的并发容器?在多

python语言中的常用容器(集合)示例详解

《python语言中的常用容器(集合)示例详解》Python集合是一种无序且不重复的数据容器,它可以存储任意类型的对象,包括数字、字符串、元组等,下面:本文主要介绍python语言中常用容器(集合... 目录1.核心内置容器1. 列表2. 元组3. 集合4. 冻结集合5. 字典2.collections模块

Spring Boot中获取IOC容器的多种方式

《SpringBoot中获取IOC容器的多种方式》本文主要介绍了SpringBoot中获取IOC容器的多种方式,包括直接注入、实现ApplicationContextAware接口、通过Spring... 目录1. 直接注入ApplicationContext2. 实现ApplicationContextA

linux配置podman阿里云容器镜像加速器详解

《linux配置podman阿里云容器镜像加速器详解》本文指导如何配置Podman使用阿里云容器镜像加速器:登录阿里云获取专属加速地址,修改Podman配置文件并移除https://前缀,最后拉取镜像... 目录1.下载podman2.获取阿里云个人容器镜像加速器地址3.更改podman配置文件4.使用po

java 恺撒加密/解密实现原理(附带源码)

《java恺撒加密/解密实现原理(附带源码)》本文介绍Java实现恺撒加密与解密,通过固定位移量对字母进行循环替换,保留大小写及非字母字符,由于其实现简单、易于理解,恺撒加密常被用作学习加密算法的入... 目录Java 恺撒加密/解密实现1. 项目背景与介绍2. 相关知识2.1 恺撒加密算法原理2.2 Ja

Nginx屏蔽服务器名称与版本信息方式(源码级修改)

《Nginx屏蔽服务器名称与版本信息方式(源码级修改)》本文详解如何通过源码修改Nginx1.25.4,移除Server响应头中的服务类型和版本信息,以增强安全性,需重新配置、编译、安装,升级时需重复... 目录一、背景与目的二、适用版本三、操作步骤修改源码文件四、后续操作提示五、注意事项六、总结一、背景与

k8s容器放开锁内存限制问题

《k8s容器放开锁内存限制问题》nccl-test容器运行mpirun时因NCCL_BUFFSIZE过大导致OOM,需通过修改docker服务配置文件,将LimitMEMLOCK设为infinity并... 目录问题问题确认放开容器max locked memory限制总结参考:https://Access

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

通过Docker容器部署Python环境的全流程

《通过Docker容器部署Python环境的全流程》在现代化开发流程中,Docker因其轻量化、环境隔离和跨平台一致性的特性,已成为部署Python应用的标准工具,本文将详细演示如何通过Docker容... 目录引言一、docker与python的协同优势二、核心步骤详解三、进阶配置技巧四、生产环境最佳实践

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”