【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

相关文章

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

SpringIOC容器Bean初始化和销毁回调方式

《SpringIOC容器Bean初始化和销毁回调方式》:本文主要介绍SpringIOC容器Bean初始化和销毁回调方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录前言1.@Bean指定初始化和销毁方法2.实现接口3.使用jsR250总结前言Spring Bea

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

SQL表间关联查询实例详解

《SQL表间关联查询实例详解》本文主要讲解SQL语句中常用的表间关联查询方式,包括:左连接(leftjoin)、右连接(rightjoin)、全连接(fulljoin)、内连接(innerjoin)、... 目录简介样例准备左外连接右外连接全外连接内连接交叉连接自然连接简介本文主要讲解SQL语句中常用的表

如何高效移除C++关联容器中的元素

《如何高效移除C++关联容器中的元素》关联容器和顺序容器有着很大不同,关联容器中的元素是按照关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的,本文介绍了如何高效移除C+... 目录一、简介二、移除给定位置的元素三、移除与特定键值等价的元素四、移除满足特android定条件的元

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很