红黑树的左旋、右旋和颜色变换

基本概念

红黑树是一种自平衡的二叉搜索树。树中的每一个结点的颜色不是黑色就是红色。

红黑树可以视为一棵扩充二叉树,用外部结点表示空指针。

二叉树的存储结构是使用二叉链表或者三叉链表来表示的,每个结点都存在指向该节点左右孩子的指针。但是叶子结点是没有孩子结点的,所以将叶子结点中指向孩子节点的指针置为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的查找里面呢

因为这是一个纯粹的内存问题,不存在索引问题。

原文地址:https://www.cnblogs.com/hxhlrq/p/13335841.html