红黑树-1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28788687/article/details/79509121
  • 为什么我们需要红黑二叉树
    要开始对红黑二叉树的学习,我们要从二叉查找树,开始说起,二叉查找树因为其插入算法的缺陷,有时会导致查找算法出现糟糕的情况。而前面的2-3查找树,得益于我们加上的”限制“,得益于其特殊的插入操作,能够保证树的平衡性,为其查找算法提供保证,但我们会看见我们要处理的情况仿佛有点过分的多。而要想用较少的代码实现2-3平衡性,而这种代价无非是算法中最重要的一种策略:用空间换时间,回想归并排序,真是因为其花费的线性空间复杂度才使得归并排序无论什么情况下都表现出较好的性能,而非快排一样出现糟糕的情况。

  • 基本思想

  • 为了将二叉查找树的简洁高效的查找算法与2-3查找树的高效的平衡插入算法像结合。我们将用标准的二叉查找树和一些额外的信息(替换3-节点)来表示2-3查找树。我们将3-节点分解为2-节点,具体做法是将3-节点的左键分解出去成为一个2-节点,成为右键的2-节点 的左孩子(相连的链接称为红链接(事实上我们将链接的颜色储存在节点中)),而原3-节点的左链接和中链接分别称为“左键”节点的孩子
    这里写图片描述

  • 等价定义

    1. 红链接均为左链接
    2. 没有任何节点同时与两个红链接相连
    3. 该树是完全黑平衡的。(即空链接到根节点的路径上黑链接数量相等)

      • 为什么我们要引入红色节点
        基于红黑树的定义,我们可以直观感受到她对平衡性的控制,黑色高度被要求完全一样,这是对平衡性的直接控制。但是我们即将看见,平衡性的控制是需要我们对其进行维护。而平衡性与维护开销是一对矛盾,保证绝对的平衡性固然好,但是另一方面却代表着维护开销很大。这就是为什么我们倾向于AVL等,而不是一颗满二叉树,本质上我们追求的是在平衡性(查找性能)和维护开销之间的高效权衡。基于这一思路,红黑树引入了红色节点就是为了实现这一高效的平衡,红色节点的引入使得红黑树可以有一定限度的不平衡,但我们红色节点(链接)不能连续出现,这一限制又能确保不平衡性被限制在一定的程度内。
  • 旋转
    在我们的一些操作中,我们可能会得到红色链接或者是连续的两个红链接,我们采用的是类似我们在AVL树中的单旋转操作。但不同的是我们红黑树的旋转操作不会降低树的高度问题。???那么高度问题如何解决呢????而仅仅改变红链接的方向。
  • 左旋转 与 右旋转
    旋转前:

    旋转后:
    这里写图片描述
    2.向一个2-节点中插入新键
    向只含有一个2-节点的红黑树插入一个新键,如果小于老键,我们调增加一个红色节点即可,而若大于老键我们则会产生一个红色的右链接(我们假定每次插入的都是红节点,但我们可以后面会提到我们能更改颜色),这是我们不予许的这时我们能够通过一次左旋转来将红链接转到左边去。这时我们要重新设置根链接。
    这里写图片描述
    3.向树底部的2-节点插入新键
    当新键节点的父节点为2-节点时,我们依旧可以采用上面的策略。但新节点为父节点的右链接时,则父节点直接成为了一个3-节点,而但新节点是父节点的右节点时,我们不予许出现右链接,我们可以通过一次左旋转来修正它。
    这里写图片描述
  • 向一个3-节点插入新键
    【 1 】 . 新键大于树中两个键(下面两种情况我们将看见都会转变成这一种情况)
    新节点被连接到3-节点的右链接,该链接为红色。根节点为中间大小的键,它有两条红链接分别和较小和较大的节点相连。如果我们将两条链接的颜色都由红变黑,那么我们就得到了一颗由三个节点组成、高为2的平衡树。
    【 2 】 .新键小于树中两个键
    新节点被连接到最左边的空链接,这样就产生了两条连续的红链接。此时我们只需要将上层的红链接右旋转即可得到第一种情况(中值键为根节点并和其他两个节点用红链接相连)。
    【 3 】 .新键在树中两个键之间
    这又会产生两条连续的红链接,一条红色左链接接一条红色右链接。此时我们只需要将下层的红链接左旋转即可得到第二种情况。或者说是经过一次类似AVL树中的左右旋转。
    这里写图片描述
  • 讨论颜色转化问题
    当一个节点有两个红色子节点时,我们选择用重新染色来遵守“不予许存在右链接这一规则”。如前面(3 - 【 1 】)提到的一种策略一样。我们可以将两个红子节点染成黑色,这样无非就是树高增加1而已。(正如2-3树一样,这也是树高增长的唯一方式,以及根节点一定为黑色)而另一种方式是将,两个红色子节点染成黑色,反而将原来父节点染成红色。注意这里将父节点染成红色仿佛是一个错误的做法,如果该父节点是另一个节点的右节点时,这样不就违法我们的规则了吗?请往下看,下面我们会看到这里的“问题”,我们是怎么解决的。
  • 向根底部的3- 节点插入新键
    当我们在底部的3-节点插入新键时,根据上面讨论的结果,都能通过旋转变化为上面的第一种结果,特别的是我们不在采用它那里的染色规则,而是采用上面的第二种染色规则,之所以这样做是为了保证树的平衡性。这样我们会产生一个红链接,相当于在父节点中插入一个新键,那么我们该如何解决呢? 我们完全可以同样的插入方法,进行处理。就这样将红链接一直往上传播,直到我们遇见2-节点,或根节点。当红链接传播成为新的根节点时,我们将根节点染成黑色即可。只要我们谨慎的使用旋转操作和染色问题,我们就不会违反我们的规定。
    具体如下
    顺序完成下面的操作:
    【 1 】如果右子节点是红色而左子节点是黑色时,进行左旋转。
    【 2 】如果右子节点是红色而左子节点是红色时,进行右旋转。
    【 3 】 左右节点都是红色时,我们进行重新染色。
    这里写图片描述

  • 红黑树的高度
    一颗大小为N的红黑树,高度不会超过 2lg N.

猜你喜欢

转载自blog.csdn.net/qq_28788687/article/details/79509121
今日推荐