K:红黑树
红黑树由AVL树改进而来,红黑树与AVL都是平衡结构的树。对于AVL树,其每次插入操作都需要从根节点处开始判断该树是否失去平衡,从而做出相应的调整。且其调整过程较为麻烦,每次都需要判断其左右两棵子AVL树的深度情况。相对于红黑树,其将关注点从AVL树的左右两棵子树的深度的失衡情况(也就是平衡因子)转变为了树的节点的颜色。从原先的由于AVL树的深度不一导致的失衡而对该二叉树进行调整转变为了由于该二叉树的相关节点的颜色不符合规则,而对该二叉树进行相应的调整的情况。
红黑树的相关规则:
- 每个节点要么是黑色,要么是红色
- 根节点是黑色的
- 每个叶节点(NULL或空节点)是黑色
- 每个红色节点的两个叶子节点都是黑色的(也就是说并不存在两个连续的红色节点)
- 从任意一个节点到其子树中的所有路径都包含相同数目的黑色节点
如下图所示:
通过这五条性质,可以通过数学证明来证明,满足这五条性质的二叉树可以将查找和删除操作维持在对数时间内。当我们插入和删除操作时,所做的一切操作都是为了调整树使之符合这五条性质。以下介绍调整树的相关结构的两个基本操作:
- 左旋:
- 右旋:
旋转的目的是将节点多的一支出让节点给另一个节点少的一支
在讲解相关的操作之前,明确下各个节点的叫法:
以下讨论红黑树的两个基本操作:
1. 插入:
对于插入操作,我们插入的节点均将其着色为红色,如果插入的节点为黑色节点,那就违背了性质五,需要进行大规模的调整,如果我们插入的是红色节点,那就在插入节点的父节点也是也是红色的时候违反性质四或者是当插入的节点是根节点时,违反性质二。相对而言,其调整程度小于插入节点为黑色节点的情况。需要注意的是红黑树的插入过程与二叉搜索树的相同,只是之后再进行相应的调整。
下面是可能遇到的插入的几种情况:
当插入的节点为根节点的时候,只需要直接将该节点涂黑即可。
当要插入的节点的父节点为黑色的时候,这时插入一个红色的节点并没有对着五个性质产生破坏。所以直接插入不用进行调整。
如果插入的节点的父节点是红色节点,这时就需要分情况进行相应的调整操作,以保证红黑树的相关性质
插入的节点的父节点为红色节点,且其父节点是祖父节点的左分支的情况:
这时,也需要分两种情况进行讨论:- 叔叔节点为红色节点,如下情况所示:
这时,只需要将父节点和叔叔节点涂成黑色,将祖父节点涂成红色即可。
叔叔节点为黑色节点
当叔叔节点为黑色节点的时候,也分两种情况:
- 插入节点是父节点的左分支,如下情况所示:
这时,违背了性质四,我们需要对其进行相应的调整,使满足红黑树的相关性质。我们可以通通过对其祖父节点进行右旋同时将祖父节点和父节点的颜色进行互换,这样就变成了:
经过调整之后的红黑树可以符合性质四并且不对其它性质产生破坏
- 插入节点为父节点的右分支,如下情况所示:
我们可以先对父节点进行左旋操作,变成如下所示:如果我们把原先的父节点看做是新的要插入的节点,把原先要插入的节点看做是新的父节点,那就变成了当要插入的节点在父节点的左支的情况,这样就可以按照当要插入的节点在父节点的左分支的情况进行旋转,旋转后变成如下的情况:
插入的节点的父节点为红色节点,且其父节点是祖父节点的右分支,这种情况与插入的节点的父节点为红色节点,且其父节点为祖父节点的右分支的情况互为镜像。为此,只需要将其左节点和右节点进行互换即可。
2. 删除:
对于删除操作,其过程类似于普通的二叉搜索树的删除过程,分为以下三种情况:
当删除的元素为叶节点的时候,直接将其进行删除
当删除的元素有一个子节点时,可以将子节点直接移动到被删除元素的位置,代替被删除的元素
被删除节点有两个儿子。那么,先找出它的后继节点;然后把“它的后继节点的内容”复制给“该节点的内容”;之后,删除“它的后继节点”。在这里,后继节点相当于替身,在将后继节点的内容复制给"被删除节点"之后,再将后继节点删除。这样就巧妙的将问题转换为"删除后继节点"的情况了,下面就考虑后继节点。 在"被删除节点"有两个非空子节点的情况下,它的后继节点不可能是双子非空。既然"被删除节点的后继节点"不可能双子都非空,就意味着"该节点的后继节点"要么没有儿子,要么只有一个儿子。若没有儿子,则按"情况1 "进行处理;若只有一个儿子,则按"情况2 "进行处理。如图:
将被删除元素与其右支的最小元素互换,变成如下图所示:
然后再将被删除元素删除:
加入颜色之后,被删除元素和后继元素互换只是值得互换,并不互换颜色,这个要注意。以下所讲的被删除元素,均指互换后的被删除元素
下面开始讲一下红黑树删除的规则:
当被删除元素为红时,对五条性质没有什么影响,直接删除。
当被删除元素为黑且为根节点时,直接删除。
当被删除元素为黑,且有一个右子节点为红时,将右子节点涂黑放到被删除元素的位置,如图:
其中节点a为替换后的被删除节点
变成:
- 当被删除元素为黑,且兄弟节点为黑,兄弟节点两个孩子也为黑,父节点为红,此时,交换兄弟节点与父节点的颜色;NULL元素是指每个叶节点都有两个空的,颜色为黑的NULL元素,需要他的时候就可以把它看成两个黑元素,不需要的时候可以忽视他。
如图:
由
变成:
5.当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的右支为红色,这个时候需要交换兄弟与父亲的颜色,并把父亲涂黑、兄弟的右支涂黑,并以父节点为中心左转。如图:
由:
变成:
6.当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的左支为红色,这个时候需要先把兄弟与兄弟的左子节点颜色互换,进行右转,然后就变成了规则5一样了,在按照规则5进行旋转。如图:
由
先兄弟与兄弟的左子节点颜色互换,进行右转,变成:
然后在按照规则5进行旋转,变成:
7.当被删除元素为黑且为父元素的右支时,跟情况5.情况6 互为镜像。
8.被删除元素为黑且兄弟节点为黑,兄弟节点的孩子为黑,父亲为黑,这个时候需要将兄弟节点变为红,再把父亲看做那个被删除的元素(只是看做,实际上不删除),看看父亲符合哪一条删除规则,进行处理变化如图:
由:
变成:
9.当被删除的元素为黑,且为父元素的左支,兄弟节点为红色的时候,需要交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋,就变成了情况4,在按照情况四进行操作即可,变化如下:
由:
交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋 变成:
在按照情况四进行操作,变成:
博文参考自:最容易懂得红黑树
K:红黑树的更多相关文章
- 编程算法 - 最小的k个数 红黑树 代码(C++)
最小的k个数 红黑树 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出当中的最小k个数. 使用红黑树(multiset) ...
- jdk源码分析红黑树——插入篇
红黑树是自平衡的排序树,自平衡的优点是减少遍历的节点,所以效率会高.如果是非平衡的二叉树,当顺序或逆序插入的时候,查找动作很可能会遍历n个节点 红黑树的规则很容易理解,但是维护这个规则难. 一.规则 ...
- 谈c++ pb_ds库(二) 红黑树大法好
厉害了,没想到翻翻pb_ds库看到这么多好东西,封装好的.现成的splay.红黑树.avl... 即使不能在考场上使用也可以用来对拍哦 声明/头文件 #include <ext/pb_ds/tr ...
- 算法设计和数据结构学习_5(BST&AVL&红黑树简单介绍)
前言: 节主要是给出BST,AVL和红黑树的C++代码,方便自己以后的查阅,其代码依旧是data structures and algorithm analysis in c++ (second ed ...
- 通过分析 JDK 源代码研究 TreeMap 红黑树算法实现
本文转载自http://www.ibm.com/developerworks/cn/java/j-lo-tree/ 目录: TreeSet 和 TreeMap 的关系 TreeMap 的添加节点 Tr ...
- 研究jdk关于TreeMap 红黑树算法实现
因为TreeMap的实现方式是用红黑树这种数据结构进行存储的,所以呢我主要通过分析红黑树的实现在看待TreeMap,侧重点也在于如何实现红黑树,因为网上已经有非常都的关于红黑树的实现.我也看了些,但是 ...
- BZOJ-3227 红黑树(tree) 树形DP
个人认为比较好的(高端)树形DP,也有可能是人傻 3227: [Sdoi2008]红黑树(tree) Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1 ...
- 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...
- java中treemap和treeset实现(红黑树)
java中treemap和treeset实现(红黑树) TreeMap 的实现就是红黑树数据结构,也就说是一棵自平衡的排序二叉树,这样就可以保证当需要快速检索指定节点. TreeSet 和 Tre ...
随机推荐
- FunDA(11)- 数据库操作的并行运算:Parallel data processing
FunDA最重要的设计目标之一就是能够实现数据库操作的并行运算.我们先重温一下fs2是如何实现并行运算的.我们用interleave.merge.either这几种方式来同时处理两个Stream里的元 ...
- CISSP一次通过指南(文末附福利)
2017年12月19日,在上海黄浦区汉口路亚洲大厦17层通过了CISSP认证考试,拖拉了一年,终于成绩还算令人满意,为攒人品将自己一年多的复习心得和大家分享,希望能够帮到需要考证的朋友. 本文作者:i ...
- Django服务器启动时指定端口和IP方法
python manager.py runserver 127.0.0.1:8001
- vmware安装——CentOS-6.5和Mysql
1.新建虚拟机 2.安装centos6.5 3.centos设置 查看网络 4.vmware设置网络连接 关闭selinux [root@china ~]# vim /etc/selinux/conf ...
- 四、CLR执行程序集中代码和IL代码简介
三.加载公共语言运行时中介绍了在安装了.Net Framework中加载公共语言运行时,公共语言运行时加载程序集的过程.以及通过vs stdio设置源码编译的目标平台的过程. 本问主要介绍公共语言加载 ...
- scala combineByKey用法说明
语法是: combineByKey[C]( createCombiner: V => C, mergeValue: (C, V) => C, mergeCombiners: ( ...
- php如何使用rabbitmq实现发布消息和消费消息(tp框架)(第一篇)
1,默认已经安装好了rabbitmq: 参考 http://www.cnblogs.com/spicy/p/7017603.html 2,安装rabbitmq客户端: 方法1: pecl 扩展安装 ...
- phpredisadmin 莫名其妙错误,打开了无法显示任何数据
一直用的好好的,某天突然只有页面基本框架,redis数据看不到了. 查日志嘛... PHP Fatal error: Allowed memory size of 134217728 bytes e ...
- 为android游戏开发-准备的地图编辑器-初步刷地图
采用多文理混合,单页面支持8张文理进行刷绘
- gulp4.0 前端构建脚手架
最近看了下gulp4.0的升级,感觉和3.0相比变化还是比较大的,很多3.0的写法和插件会出现一些莫名其妙的变化,详细的变化就先不说了,这里我直接把我配置好的代码拿过来吧,方便各位可以更好的学习和使用 ...