zoukankan      html  css  js  c++  java
  • 红黑树的左旋、右旋和颜色变换

    基本概念

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

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

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

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

  • 相关阅读:
    Implementing Automation Collections
    PSP 2.0降级至1.5详细教程(转)
    Delphi 7 过期的问题
    Delphi读写COM复合文档用户自定义属性参考代码
    十大经典误会
    Office檔案格式(Office文件格式)
    将表格粘贴为Word可识别的格式
    对字符编码与Unicode,ISO 10646,UCS,UTF8,UTF16,GBK,GB2312的理解
    如何识别键盘左右的shift,Ctrl或Alt键
    SRT File Format
  • 原文地址:https://www.cnblogs.com/hxhlrq/p/13335841.html
Copyright © 2011-2022 走看看