红黑树由AVL树改进而来,红黑树与AVL都是平衡结构的树。对于AVL树,其每次插入操作都需要从根节点处开始判断该树是否失去平衡,从而做出相应的调整。且其调整过程较为麻烦,每次都需要判断其左右两棵子AVL树的深度情况。相对于红黑树,其将关注点从AVL树的左右两棵子树的深度的失衡情况(也就是平衡因子)转变为了树的节点的颜色。从原先的由于AVL树的深度不一导致的失衡而对该二叉树进行调整转变为了由于该二叉树的相关节点的颜色不符合规则,而对该二叉树进行相应的调整的情况。

红黑树的相关规则:

  1. 每个节点要么是黑色,要么是红色
  2. 根节点是黑色的
  3. 每个叶节点(NULL或空节点)是黑色
  4. 每个红色节点的两个叶子节点都是黑色的(也就是说并不存在两个连续的红色节点)
  5. 从任意一个节点到其子树中的所有路径都包含相同数目的黑色节点

如下图所示:

通过这五条性质,可以通过数学证明来证明,满足这五条性质的二叉树可以将查找和删除操作维持在对数时间内。当我们插入和删除操作时,所做的一切操作都是为了调整树使之符合这五条性质。以下介绍调整树的相关结构的两个基本操作:

  1. 左旋:

  1. 右旋:

旋转的目的是将节点多的一支出让节点给另一个节点少的一支

在讲解相关的操作之前,明确下各个节点的叫法:

以下讨论红黑树的两个基本操作:

1. 插入:

  对于插入操作,我们插入的节点均将其着色为红色,如果插入的节点为黑色节点,那就违背了性质五,需要进行大规模的调整,如果我们插入的是红色节点,那就在插入节点的父节点也是也是红色的时候违反性质四或者是当插入的节点是根节点时,违反性质二。相对而言,其调整程度小于插入节点为黑色节点的情况。需要注意的是红黑树的插入过程与二叉搜索树的相同,只是之后再进行相应的调整。

下面是可能遇到的插入的几种情况:

  1. 当插入的节点为根节点的时候,只需要直接将该节点涂黑即可。

  2. 当要插入的节点的父节点为黑色的时候,这时插入一个红色的节点并没有对着五个性质产生破坏。所以直接插入不用进行调整。

  3. 如果插入的节点的父节点是红色节点,这时就需要分情况进行相应的调整操作,以保证红黑树的相关性质

    1. 插入的节点的父节点为红色节点,且其父节点是祖父节点的左分支的情况:
      这时,也需要分两种情况进行讨论:

      1. 叔叔节点为红色节点,如下情况所示:

      这时,只需要将父节点和叔叔节点涂成黑色,将祖父节点涂成红色即可。

      1. 叔叔节点为黑色节点

        当叔叔节点为黑色节点的时候,也分两种情况:

        1. 插入节点是父节点的左分支,如下情况所示:

        这时,违背了性质四,我们需要对其进行相应的调整,使满足红黑树的相关性质。我们可以通通过对其祖父节点进行右旋同时将祖父节点和父节点的颜色进行互换,这样就变成了:

        经过调整之后的红黑树可以符合性质四并且不对其它性质产生破坏

        1. 插入节点为父节点的右分支,如下情况所示:


        我们可以先对父节点进行左旋操作,变成如下所示:

        如果我们把原先的父节点看做是新的要插入的节点,把原先要插入的节点看做是新的父节点,那就变成了当要插入的节点在父节点的左支的情况,这样就可以按照当要插入的节点在父节点的左分支的情况进行旋转,旋转后变成如下的情况:

    2. 插入的节点的父节点为红色节点,且其父节点是祖父节点的右分支,这种情况与插入的节点的父节点为红色节点,且其父节点为祖父节点的右分支的情况互为镜像。为此,只需要将其左节点和右节点进行互换即可。

2. 删除:

  对于删除操作,其过程类似于普通的二叉搜索树的删除过程,分为以下三种情况:

  1. 当删除的元素为叶节点的时候,直接将其进行删除

  2. 当删除的元素有一个子节点时,可以将子节点直接移动到被删除元素的位置,代替被删除的元素

  3. 被删除节点有两个儿子。那么,先找出它的后继节点;然后把“它的后继节点的内容”复制给“该节点的内容”;之后,删除“它的后继节点”。在这里,后继节点相当于替身,在将后继节点的内容复制给"被删除节点"之后,再将后继节点删除。这样就巧妙的将问题转换为"删除后继节点"的情况了,下面就考虑后继节点。 在"被删除节点"有两个非空子节点的情况下,它的后继节点不可能是双子非空。既然"被删除节点的后继节点"不可能双子都非空,就意味着"该节点的后继节点"要么没有儿子,要么只有一个儿子。若没有儿子,则按"情况1 "进行处理;若只有一个儿子,则按"情况2 "进行处理。如图:

将被删除元素与其右支的最小元素互换,变成如下图所示:

然后再将被删除元素删除:

加入颜色之后,被删除元素和后继元素互换只是值得互换,并不互换颜色,这个要注意。以下所讲的被删除元素,均指互换后的被删除元素

下面开始讲一下红黑树删除的规则:

  1. 当被删除元素为红时,对五条性质没有什么影响,直接删除。

  2. 当被删除元素为黑且为根节点时,直接删除。

  3. 当被删除元素为黑,且有一个右子节点为红时,将右子节点涂黑放到被删除元素的位置,如图:

其中节点a为替换后的被删除节点

变成:

  1. 当被删除元素为黑,且兄弟节点为黑,兄弟节点两个孩子也为黑,父节点为红,此时,交换兄弟节点与父节点的颜色;NULL元素是指每个叶节点都有两个空的,颜色为黑的NULL元素,需要他的时候就可以把它看成两个黑元素,不需要的时候可以忽视他。
    如图:

变成:

5.当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的右支为红色,这个时候需要交换兄弟与父亲的颜色,并把父亲涂黑、兄弟的右支涂黑,并以父节点为中心左转。如图:
由:

变成:

6.当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的左支为红色,这个时候需要先把兄弟与兄弟的左子节点颜色互换,进行右转,然后就变成了规则5一样了,在按照规则5进行旋转。如图:

先兄弟与兄弟的左子节点颜色互换,进行右转,变成:

然后在按照规则5进行旋转,变成:

7.当被删除元素为黑且为父元素的右支时,跟情况5.情况6 互为镜像。

8.被删除元素为黑且兄弟节点为黑,兄弟节点的孩子为黑,父亲为黑,这个时候需要将兄弟节点变为红,再把父亲看做那个被删除的元素(只是看做,实际上不删除),看看父亲符合哪一条删除规则,进行处理变化如图:
由:

变成:

9.当被删除的元素为黑,且为父元素的左支,兄弟节点为红色的时候,需要交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋,就变成了情况4,在按照情况四进行操作即可,变化如下:
由:

交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋 变成:

在按照情况四进行操作,变成:

博文参考自:最容易懂得红黑树

K:红黑树的更多相关文章

  1. 编程算法 - 最小的k个数 红黑树 代码(C++)

    最小的k个数 红黑树 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出当中的最小k个数. 使用红黑树(multiset) ...

  2. jdk源码分析红黑树——插入篇

    红黑树是自平衡的排序树,自平衡的优点是减少遍历的节点,所以效率会高.如果是非平衡的二叉树,当顺序或逆序插入的时候,查找动作很可能会遍历n个节点 红黑树的规则很容易理解,但是维护这个规则难. 一.规则 ...

  3. 谈c++ pb_ds库(二) 红黑树大法好

    厉害了,没想到翻翻pb_ds库看到这么多好东西,封装好的.现成的splay.红黑树.avl... 即使不能在考场上使用也可以用来对拍哦 声明/头文件 #include <ext/pb_ds/tr ...

  4. 算法设计和数据结构学习_5(BST&AVL&红黑树简单介绍)

    前言: 节主要是给出BST,AVL和红黑树的C++代码,方便自己以后的查阅,其代码依旧是data structures and algorithm analysis in c++ (second ed ...

  5. 通过分析 JDK 源代码研究 TreeMap 红黑树算法实现

    本文转载自http://www.ibm.com/developerworks/cn/java/j-lo-tree/ 目录: TreeSet 和 TreeMap 的关系 TreeMap 的添加节点 Tr ...

  6. 研究jdk关于TreeMap 红黑树算法实现

    因为TreeMap的实现方式是用红黑树这种数据结构进行存储的,所以呢我主要通过分析红黑树的实现在看待TreeMap,侧重点也在于如何实现红黑树,因为网上已经有非常都的关于红黑树的实现.我也看了些,但是 ...

  7. BZOJ-3227 红黑树(tree) 树形DP

    个人认为比较好的(高端)树形DP,也有可能是人傻 3227: [Sdoi2008]红黑树(tree) Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1 ...

  8. 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树

    http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...

  9. java中treemap和treeset实现(红黑树)

    java中treemap和treeset实现(红黑树)   TreeMap 的实现就是红黑树数据结构,也就说是一棵自平衡的排序二叉树,这样就可以保证当需要快速检索指定节点. TreeSet 和 Tre ...

随机推荐

  1. 使用pipreqs生成项目依赖

    作用 导出当前项目的环境依赖 使用 # 安装 pip3 install pipreqs # 导出项目环境依赖 pipreqs ./ # 如果是Windows系统,会报编码错误 (UnicodeDeco ...

  2. .NET Windows Form 改变窗体类名(Class Name)有多难?

    研究WinForm的东西,是我的一个个人兴趣和爱好,以前做的项目,多与WinForm相关,然而这几年,项目都与WinForm没什么关系了,都转为ASP.NET MVC与WPF了.关于今天讨论的这个问题 ...

  3. libevent源码剖析

    libevent是一个使用C语言编写的,轻量级的开源高性能网络库,使用者很多,研究者也很多.由于代码简洁,设计思想简明巧妙,因此很适合用来学习,提升自己C语言的能力. libevent有这样显著地几个 ...

  4. 使用SUI框架下的<a>标签点击跳转页面不刷新的问题

    最近写好了几个页面,今天试着将各个页面的链接打通,然后问题就来了...(╯︵╰) 这里看一下原来想要实现的两个页面跳转的效果--点击图一标注的栏目可以跳转到一个新的页面图二... 按照之前写a标签的跳 ...

  5. Requests库入门实例

    爬虫入门5个实例 实例1:京东商品页面的爬取 import requests def getHTMLText(url): try: r = requests.get(url,timeout = 30) ...

  6. js delete删除对象属性,delete删除不了变量及原型链中的变量

    js delete删除对象属性,delete删除不了变量及原型链中的变量 一.delete删除对象属性 function fun(){ this.name = 'gg'; } var obj = ne ...

  7. H02-启动hdfs时可能遇到的几个问题

    启动hdfs时,有时候可能会遇到这样几种情况: 1)在主节点上执行start-dfs.sh命令启动hdfs,无法启动datanode. 2)在主节点上行启动hdfs,启动成功了,在各个节点上使用jps ...

  8. 对Deeplung检测+两样性分类的一个整合

    整体的流程分为以下几步: 读取原始数据(.mhd文件)——> 生成mask ——> 对数据预处理 ——> 执行检测 ——> 对检测结果进行分类 ——>可视化 懒一点,不贴 ...

  9. (转)mysql的sql_mode合理设置

    mysql的sql_mode合理设置 目录          http://xstarcd.github.io/wiki/MySQL/MySQL-sql-mode.html http://dev.my ...

  10. 在windows里安装系统7、8、10或Offcie或Visio等推荐的激活工具

    不多说,直接上干货! (1)激活Windows或者Office前,你务必先进去KMSAuto Net的System界面,安装KMS-host Service; (2)然后回到Main主界面,选择Act ...