zoukankan      html  css  js  c++  java
  • 红黑树

    AVL-tree、RB-tree、AA-tree均可以实现平衡的二叉查找树,虽然相对于一般的二叉搜索树其插入、删除节点的平均时间会比较长,但它们可以避免极验证应付的最坏的情况--树高度不平衡。

    平衡二叉查找树所谓的平衡并不是绝对的平衡,而是要求任何一个节点的左右子树高度相差不会超过1,此时仍能够保证树的“对数深度”。

    在学习红黑树之前要先学习AVL树,了解一些旋转操作是怎么进行的。

     

    如上图所示,X节点本来是平衡的,插入一个新节点后“平衡被破坏”了,这可以分为4种情况:

    1. 插入节点位于X的左子节点的左子树--左左;
    2. 插入节点位于X的左子节点的右子树--左右;
    3. 插入节点位于X的右子节点的左子树--右左;
    4. 插入节点位于X的右子节点的右子树--右右。

    情况1、4彼此对称,称为外侧插入,可以采用单旋操作调整解决;情况2、3彼此对称,称为内侧插入,可以采用双旋转操作调整解决。

    单旋转

    插入新节点11出现情况1的调整策略:把中k1作为其左子孩子k2的右孩子,而k2原先的右孩子作为现在k1的左孩子。

    出现情况4的调整策略类同。

    双旋转

     

    插入新节点15出现情况2的调整策略:先让k2和k1做一次单旋转,再让k2和k3做一次单旋转。

    出现情况3的调整策略类同。

    红黑树RB-tree

    C++中的set和map底层用的就是红黑树。

    RB-tree是满足以下4个条件的二叉查找树:

    1. 每个节点不是红色就是黑色
    2. 根节点为黑色
    3. 红节点的子节点必须是黑色
    4. 任一节点至NULL(树尾端)的每一条路径上,所含黑节点的数目必须相同

    红黑树并不要求左右子树高度差控制在1以内,它的平衡条件比AVL树弱。然而红黑树通常能够导致良好的平衡状态,经验告诉我们,红黑树的平均搜索效率和AV-tree几乎相等,但是其插入节点的开销相对较低,实践中发生旋转的次数相对较少。

    以下所有操作,在新插入节点后,首先将新节点设为红色。

    按照二叉查找树的规则插入新节点后,如果新增节点的父节点为黑,则直接插入。否则分为4种情况(在此作一些符号约定,新增节点为X,其父节点为P,祖父节点为G,伯父节点为S,曾祖父节点为GG):

    1. S为黑,且X为外侧插入。P,G做一次单旋转,并更改P,G的颜色。
    2. S为黑,且X为内侧插入。 X,P做一次单旋转,并更改X和P的颜色。再对X,G做一次单旋转。
    3. S为红,且X为外侧插入。 P,G做一次单旋转,并更改X的颜色。此时如果GG为黑,一切搞定;否则,还得继续往上做,直到不再有父子节点连续为红的情况。
    4.  S为红,且X为内侧插入。直接更改P,S,G的颜色。此时如果GG为黑,一切搞定;否则,还得继续往上做,直到不再有父子节点连续为红的情况。

    为了避免上述情况3、4中GG也为红的情况发生,我们设计一个“自顶向下”的红黑树。假设新增节点为A,那么就延着从根节点到A的路径,只要看到某个节点X的两个子节点皆为红色,就把这两个子节点改为黑色,同时把X改为红色。但是如果此时X的父节点也是红色(注意此时X的伯父节点已经不可能是红色),就像上述情况1那样作一次单旋转改变颜色,或像情况2那样做一些双旋转再改变颜色。

  • 相关阅读:
    06_Python的数据类型3元组,集合和字典_Python编程之路
    05_Python的数据类型2列表_Python编程之路
    03_Linux的目录结构_我的Linux之路
    03-第一个脚本程序以及输入输出_Python编程之路
    系统命令学习
    《构建之法》读书笔记
    Android开发入门
    Android 手机进入不了fastboot模式的解决方案
    error:“Unexpected namespace prefix "xmlns" found for tag LinearLayout”
    2014.2.13自我能力量化
  • 原文地址:https://www.cnblogs.com/aukle/p/3223834.html
Copyright © 2011-2022 走看看