红黑树的左旋、右旋和颜色变换
基本概念
红黑树是一种自平衡的二叉搜索树。树中的每一个结点的颜色不是黑色就是红色。
红黑树可以视为一棵扩充二叉树,用外部结点表示空指针。
二叉树的存储结构是使用二叉链表或者三叉链表来表示的,每个结点都存在指向该节点左右孩子的指针。但是叶子结点是没有孩子结点的,所以将叶子结点中指向孩子节点的指针置为NULL,NULL为空指针。在红黑树中,使用外部结点表示空指针,就是使用外部结点表示NULL,这个结点是在物理内存上是不存在的,是想象出来以便于理解的。
红黑树的特性
1.根节点和所有的外部结点都是黑色的
2.从根节点到外部结点的图中没有连续两个结点的颜色是红色
3.所有从根到外部结点的路径上都有相同数目的黑色结点
结点的阶:从红黑树中任一结点x出发(不包括结点x),到达一个外部结点的任一路径上的黑结点个数叫做结点x的黑高度,亦称结点的阶,记作bh(x),红黑树的高度定义为其根节点的黑高度
变换规则
1.颜色变换
2.左旋
左旋又分为两种情况,
(1)我们操作的结点E是整棵树的根节点,那么左旋实现为下面步骤
a. 将结点s的左子树变化为E的右子树。也就是将E.rightchild值修改为S.leftchild后将S.leftchild置为NULL,将S.leftchild.parent置为结点E的指针。
b.将结点E的父结点指针parent指向结点S
c.将s结点的父结点指针parent置为NULL。
(2)我们操作的结点E有父结点,那么左旋实现为下面步骤
a. 将结点s的左子树变化为E的右子树,也就是将E.rightchild值修改为S.leftchild后将S.leftchild置为NULL,将S.leftchild.parent置为结点E的指针
b.声明一个辅助指针变量,指向结点E,即存储的是E结点的指针。将结点S的父结点指针parent修改为结点E的父指针parent的值
c.通过辅助指针变量,将结点E的父指针parent修改指向结点S。
3.右旋
右旋同样分为两种情况,与左旋情况类似,故实际操作参考左旋。
插入
首先使用二叉搜索树的插入算法将一个元素插入到红黑树中,该元素作为新的叶子结点插入到某一外部结点位置,才插入结点过程中需要为新元素染色。
注意:上述描述中一个很重要的点是,在插入元素时,是将元素作为叶子结点插入的,插入到原红黑树的外部结点。
插入结点染色情况
1.如果插入前是空树,那么新插入的元素就会成为根节点,根据特征,需要将根节点染成黑色。
2.如果红黑树非空,那么在红黑树中插入新的结点时,所有的点都默认是红色结点。
插入结点后调整和平衡过程
1.变颜色的情况: 当前结点的父亲是红色,且它的祖父结点的另一个结点(也就是叔叔结点)也是红色:
(1)把父结点设为黑色
(2)把叔叔结点也设为黑色
(3)把祖父结点,也就是父亲的父亲设置为红色(爷爷结点)
(4)把指针定义到祖父结点设为当前要操作的结点(爷爷结点)。分析点的变换规则,进行变换。
2.左旋:当前父结点是红色,叔叔结点是黑色的时候,且当前的结点时右子树,则进行左旋。左旋过程不需要进行颜色变换。
3.右旋:当前父结点时红色,叔叔结点是黑色的时候,且当前的结点是左子树,则进行右旋。右旋过程中需要进行颜色变换,具体右旋过程如下。
(1)把父结点变为黑色
(2)把祖父结点变为红色(爷爷结点)
(3)以祖父结点进行右旋(爷爷结点)
举例
为什么红黑树不能用于大型索引的快速查询
红黑树从根本上来说是一棵二叉查找树,对于千万级的大型数据,那么红黑树的深度将会有几十层甚至更多。我们以一棵只有三层的红黑树来分析。
原因1:这是一棵三层的红黑树。在数据存储时,数据库是存储在磁盘中的。我们知道,在计算机的组成中,读取速度的关系:寄存器 > 内存 > 磁盘。
假设我们在红黑树种查找数据4的结点,那么第一次就需要把数据从磁盘中读取出来,查找根节点5处存储的是不是数据4。这样就完成了一次读取磁盘。
很显然,读取根节点5时并没有读取到数据4。通过二叉树的关系,我们需要沿着结点5的左子数进行,就需要再一次把数据从磁盘中读取出来,查找到结点3中的数据。这样就完成了磁盘的第二次读取。
结点3中也没有读取到数据4,通过判断,需要沿着结点3的右子树进行。这时就需要再次把数据从磁盘中读取出来,查找到数据4,此时就又完成第三次读取磁盘。
当红黑树存储的是大型数据,红黑树的深度将会达到几十层甚至更深,那么磁盘的读取次数就会很多。
原因2:在磁盘存储时,现在的计算机的1页空间可以存储16k. 存储的一个int型却只有8个字节,读取之后还要在读取的数据中去查找。这样就造成了读取的浪费
综上所述:红黑树不能用作大型索引的根本原因为:1.读取磁盘的次数太多。2.读取浪费太多
但是红黑树为什么可以用作hashmap的查找里面呢
因为这是一个纯粹的内存问题,不存在索引问题。
posted on 2020-07-18 16:13 hxh_space 阅读(2106) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理