数据结构-红黑树原理分析
前言
在阅读HashMap源码的时候发现,java1.8的HashMap的链表实现增加了红黑树,当链表长度超过指定阈值8的时候回进行树化。
为了提高增删查的效率。
而红黑树又比较复杂,所以专门写一篇关于红黑树的文章。
概念
R-B Tree,全称是Red-Black Tree,又称为“红黑树”,是一种特殊的二叉查找树。红黑树的每个结点上都有存储位表示结点的颜色, 可以是红(Red)或黑(Black)。
了解一下百度给出的红黑树概念:
摘自百度:
红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由Rudolf Bayer发明的,当时被称为平衡二叉B树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的“红黑树”。红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的:它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。
在了解红黑树之前,先了解一下AVL树: AVL树
红黑树的统计功能要好于AVL树,因为AVL是严格平衡的,红黑树是黑平衡的,维持平衡需要额外的操作。
应用
C++的STL,map和set都是用红黑树实现的。
著名的linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块。
epoll在内核中的实现,用红黑树管理事件块。
nginx用红黑树管理timer等。
Java的TreeMap实现。
性质
红黑树不仅是自平衡二叉树还满足5个性质:
1)每个结点或红或黑
2)根结点是黑色
3)空叶子结点是黑色
4)如果一个结点是红色,那么它的子节点是黑色
5)从任意一个结点出发到空的叶子结点经过的黑结点个数相同
为了满足这五个性质,对于平衡二叉树的插入,删除就多增加了一些操作,
左旋,右旋,变色:
- 左旋
以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,其左子结点保持不变
如图:
- 右旋
以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,其右子结点保持不变。
如图:
操作
插入
插入节点面临的情况:
1.树为空,插入的结点为根结点
直接将插入的结点变成黑色
2.父亲结点为黑色结点
不需要任何操作,直接插入89就可以了。
3.父亲结点为红色结点的情况下:
3.1 叔叔节点为黑色的情况(叔叔节点不存在即为黑色)
3.1.1 父亲结点为右孩子,插入结点为左孩子
针对父结点进行右旋,此时右旋后的情况必定是3.1.3的情况,然后按照3.1.3的情况处理;
如图插入80以后变成这样了,按照上面的结论,先将80和89以89结点进行右旋,右旋后80变89的父节点,89为80的右孩子结点,此时的情况就是3.1.3情况,进行操作,将80和56颜色互换,然后对56进行左旋。此时就是上图的样子了。
3.1.2 父亲结点为左孩子,插入结点为右孩子
针对父节点进行左旋,此时左旋后的情况为3.1.4情况,然后按照3.1.4进行操作。
插入52后,以父节点48左旋,左旋后,52和59互换颜色,再以59为结点右旋即可。
3.1.3 父亲结点为右孩子,插入结点也为右孩子
将父亲结点和爷爷结点的颜色互换,然后针对爷爷结点进行一次左旋
插入82后,59和79互换颜色,然后再进行左旋即可。
3.1.4 父亲结点为左孩子,插入结点也为左孩子
将父亲结点和爷爷结点的颜色互换,然后针对爷爷结点进行一次右旋
这种情况与3.1.1情况雷同。
插入50以后,48和59颜色互换,然后对59进行左旋即可。
3.2 叔叔节点为红色的情况
将叔叔和父亲结点改为黑色,爷爷结点改为红色,然后又将爷爷节点当做插入点做此操作。
插入85后,将父亲和叔叔结点变为黑色,将爷爷节点变红,但发现爷爷节点为根节点,所以满足性质2,将根节点变为黑色即可。
- 删除
删除同样在删除操作后要进行一些列变化使树仍然具有红黑树的性质。
删除情况有三种:
1.删除结点没有儿子的情况:
1)删除结点为红色
直接删除,不影响红黑树性质
2)删除结点为黑色,其兄弟结点没有儿子
将兄弟节点变成红色,将父亲节点变成黑色,保持性质5。
如图,删除96这个节点:
删除后
3)删除结点为黑色,其兄弟结点有一个孩子不空,并且该孩子为右孩子和其父亲节点在同一边。
首先删除,当前节点83,然后把兄弟节点和父亲节点交换,在把父亲节点变黑,然后,把兄弟节点子节点变黑:
1.如果兄弟结点和兄弟结点的儿子都在右子树的话:对父亲结点进行左旋
2.如果兄弟结点和兄弟结点的儿子都在左子树的话:对父亲结点进行右旋
如图列出为第二种情况:
删除后
4)删除结点为黑色,其兄弟结点有一个孩子不空,并且该孩子为左孩子
限于篇幅和时间问题,后面的各种情况就不一一作图说明了。
如果要想自己尝试,或者看这个过程请看 红黑树演示地址
5)删除结点为黑色,其兄弟结点有两个孩子,而且兄弟结点为红色
6)删除结点为黑色,其兄弟结点有两个孩子,而且兄弟结点为黑色
二.删除结点只有一个儿子的情况:
1)删除结点为黑色,其唯一的儿子结点为红色(必定是红色,要不然不符合红黑树的第5条性质)
2)删除结点为红色,其儿子结点只能为黑:红黑树中不存在这种情况,要不然无法满足红黑树第5条性质
三.删除结点有两个儿子的情况;
以上就是删除的三种情况。
总结
红黑树的情况比较复杂,但是不难理解,首先要理解平衡二叉树,对左右旋转要理解,熟悉红黑树的五个性质,不管是删除添加都要保持这5个性质同时其又是一个特殊的平衡二叉树。
数据结构-红黑树原理分析相关推荐
- HashMap红黑树原理分析
近期学习了 HashMap 实现原理,这篇咱们了解一下红黑树的设计,相比 jdk1.7 的 HashMap 而言,jdk1.8最重要的就是引入了红黑树的设计,当hash表的单一链表长度超过 8 个的时 ...
- 为什么红黑树查询快_目前最详细的红黑树原理分析(大量图片+过程推导!!!)...
一.为什么要有红黑树这种数据结构? 我们知道ALV树是一种严格按照定义来实现的平衡二叉查找树,所以它查找的效率非常稳定,为O(log n),由于其严格按照左右子树高度差不大于1的规则,插入和删除操作中 ...
- 目前最详细的红黑树原理分析(大量图片+过程推导!!!)
一.为什么要有红黑树这种数据结构? 我们知道ALV树是一种严格按照定义来实现的平衡二叉查找树,所以它查找的效率非常稳定,为O(log n),由于其严格按照左右子树高度差不大于1的规则,插入和删除操 ...
- 数据结构 — 浅析红黑树原理以及实现
浅析红黑树原理以及实现 我们在上一篇博客认识到了平衡二叉树(AVLTree),了解到平衡二叉树的性质,其实平衡二叉树最大的作用就是查找,AVL树的查找.插入 和删除在平均 和 最坏情况下都是O(log ...
- 红黑树原理及代码实现(一)
红黑树简介 红黑树是一种自平衡的二叉查找树,它的统计性能要优于平衡二叉树,因此在很多地方都有应用,例如Java中的TreeMap,HashMap等数据结构都使用到了红黑树.红黑树对很多人来说熟悉而陌生 ...
- 红黑树 —— 原理和算法详细介绍
红黑树 -- 原理和算法详细介绍 R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为"红黑树",它一种特殊的二叉查找树.红黑树的每个节点上都有存储位 ...
- 遍历HashMap源码——红黑树原理、HashMap红黑树实现与反树型化(三)
本章将是HashMap源码的最后一章,将介绍红黑树及其实现,HashMap的remove方法与反树型化.长文预警~~ 遍历HashMap源码--红黑树原理.HashMap红黑树实现与反树型化 什么是红 ...
- HashMap红黑树原理解析
HashMap红黑树原理解析 定义: 简单来说红黑树是一种近视平衡二叉查找树,主要优点是"平衡",即左右子树高度几乎一致,以此来防止树退化为链表,通过这种方式来保障查找的时间复杂度 ...
- HashMap底层红黑树原理(超详细图解)+手写红黑树代码
在看完了小刘老师和黑马的源码视频之后,我整理了一篇HashMap的底层源码文章,学海无涯,这几天看了对红黑树的讲解,故将其整理出来 HashMap底层源码解析上 HashMap底层源码解析下 视频链接 ...
最新文章
- 消除危害 让BYOD策略更安全的几个秘诀
- 如何在golang中关闭bufio.reader_Golang 并发模型系列:1. 轻松入门流水线模型
- python 作用域 前缀_Python面试题:杂项内容
- linux kernel 2.6.36 编译升级
- 一个炒鸡好用的pdf阅读器
- 我在使用vector时候遇到的二逼问题
- 仿58网,赶集网,百姓网swfupload图片上传效果(asp.net 2.0)
- 十年前乔布斯曾试图颠覆电视行业 如今苹果终于出手了
- JavaCC报错:ERROR: Second call to constructor of static parser
- 8年测试工程师,从“点点点”成长到华为测试主管——我必须告诉你这些......(共勉)
- Vue.js目录结构
- jdk文件夹里点哪个是安装_jdk在哪个文件夹里面
- 百度信息流投放效果不稳定,意图词要怎么筛选,先测试词包还是先测试创意好?
- 读书笔记(第五周)之魔方的创新
- 防御DDoS攻击的十一种方法
- P6800- 配件识真假
- 7000 位程序员揭秘 2019 软件开发现状
- addEventListener() 的参数之passive 的用法
- Scala 环境搭建安装配置
- 星火支付/USDT承兑系统