数据结构查找算法之红黑树

基本概念

  • 红黑树,本身是一棵二叉查找树,在其基础上附加了两个要求:
    • 树中的每个结点增加了一个用于存储颜色的标志域;
    • 树中没有一条路径比其他任何路径(指的是从任何一个结点开始,一直到其子孙的叶子结点的长度)长出两倍,整棵树要接近于“平衡”的状态。
  • 红黑树对于结点的颜色设置不是任意的,需满足以下性质的二叉查找树才是红黑树:
    • 树中的每个结点颜色不是红的,就是黑的;
    • 根结点的颜色是黑的;
    • 所有为 nil 的叶子结点的颜色是黑的;(注意:叶子结点说的只是为空(nil 或 NULL)的叶子结点!)
    • 如果此结点是红的,那么它的两个孩子结点全部都是黑的;
    • 对于每个结点,从该结点到到该结点的所有子孙结点的所有路径上包含有相同数目的黑结点;
    • image.png
  • 红黑树中每个结点都有各自的黑高度,整棵树也有自己的黑高度,即为根结点的黑高度,例如图 1 中的红黑树的黑高度为 3。
  • 对于一棵具有 n 个结点的红黑树,树的高度至多为:2lg(n+1)。所以红黑树的时间复杂度为O(logn)

红黑树的旋转

  • 旋转操作分为左旋和右旋,同二叉排序树转平衡二叉树的旋转原理完全相同

红黑树中插入新节点

  • 当创建一个红黑树或者向已有红黑树中插入新的数据时,只需要按部就班地执行以下 3 步:
    • 由于红黑树本身是一棵二叉查找树,所以在插入新的结点时,完全按照二叉查找树插入结点的方法,找到新结点插入的位置;
    • 将新插入的结点结点初始化,颜色设置为红色后插入到指定位置;(将新结点初始化为红色插入后,不会破坏红黑树第 5 条的性质)
    • 由于插入新的结点,可能会破坏红黑树第 4 条的性质(若其父结点颜色为红色,就破坏了红黑树的性质),此时需要调整二叉查找树,想办法通过旋转以及修改树中结点的颜色,使其重新成为红黑树!
  • 在红黑树中插入结点时,根据插入位置的不同可分为以下 3 种情况:
  1. 插入位置为整棵树的树根。处理办法:只需要将插入结点的颜色改为黑色即可。
  2. 插入位置的双亲结点的颜色为黑色。处理方法:此种情况不需要做任何工作,新插入的颜色为红色的结点不会破坏红黑树的性质。
  3. 插入位置的双亲结点的颜色为红色。处理方法:由于插入结点颜色为红色,其双亲结点也为红色,破坏了红黑树第 4 条性质,此时需要结合其祖父结点和祖父结点的另一个孩子结点(父结点的兄弟结点,此处称为“叔叔结点”)的状态,分为 3 种情况讨论:
    • 当前结点的父节点是红色,且“叔叔结点”也是红色:破坏了红黑树的第 4 条性质,解决方案为:将父结点颜色改为黑色;将叔叔结点颜色改为黑色;将祖父结点颜色改为红色;下一步将祖父结点认做当前结点,继续判断,处理结果如图a所示
    • 当前结点的父结点颜色为红色,叔叔结点颜色为黑色,且当前结点是父结点的右孩子。解决方案:将父结点作为当前结点做左旋操作,如图b;(在进行以父结点为当前结点的左旋操作后,此种情况就转变成了第 3 种情况,处理过程跟第 3 种情况同步进行)
    • 当前结点的父结点颜色为红色,叔叔结点颜色为黑色,且当前结点是父结点的左孩子。解决方案:将父结点颜色改为黑色,祖父结点颜色改为红色,从祖父结点处进行右旋处理。如图c
      • 分析:在此种情况下,由于当前结点 F 和父结点 S 颜色都为红色,违背了红黑树的性质 4,此时可以将 S 颜色改为黑色,有违反了性质 5,因为所有通过 S 的路径其黑高度都增加了 1 ,所以需要将其祖父结点颜色设为红色后紧接一个右旋,这样这部分子树有成为了红黑树。
  • image.pngimage.pngimage.png

红黑树删除节点

  • 在红黑树中删除结点,思路更简单,只需要完成 2 步操作:
    1. 将红黑树按照二叉查找树删除结点的方法删除指定结点;
    2. 重新调整删除结点后的树,使之重新成为红黑树;(还是通过旋转和重新着色的方式进行调整)
  • 在二叉查找树删除结点时,分为 3 种情况:
    • 若该删除结点本身是叶子结点,则可以直接删除;
    • 若只有一个孩子结点(左孩子或者右孩子),则直接让其孩子结点顶替该删除结点;
    • 若有两个孩子结点,则找到该结点的右子树中值最小的叶子结点来顶替该结点,然后删除这个值最小的叶子结点。
  • 以上三种情况最终都需要删除某个结点,此时需要判断删除该结点是否会破坏红黑树的性质。判断的依据是:
  1. 如果删除结点的颜色为红色,则不会破坏;
  2. 如果删除结点的颜色为黑色,则肯定会破坏红黑树的第 5 条性质,此时就需要对树进行调整,调整方案分 4 种情况讨论:
    • 删除结点的兄弟结点颜色是红色,调整措施为:将兄弟结点颜色改为黑色,父亲结点改为红色,以父亲结点来进行左旋操作,同时更新删除结点的兄弟结点(左旋后兄弟结点发生了变化),如下图所示:image.png
    • 删除结点的兄弟结点及其孩子全部都是黑色的,调整措施为:将删除结点的兄弟结点设为红色,同时设置删除结点的父结点标记为新的结点,继续判断;
    • 删除结点的兄弟结点是黑色,其左孩子是红色,右孩子是黑色。调整措施为:将兄弟结点设为红色,兄弟结点的左孩子结点设为黑色,以兄弟结点为准进行右旋操作,最终更新删除结点的兄弟结点;
    • 删除结点的兄弟结点是黑色,其右孩子是红色(左孩子不管是什么颜色),调整措施为:将删除结点的父结点的颜色赋值给其兄弟结点,然后再设置父结点颜色为黑色,兄弟结点的右孩子结点为黑色,根据其父结点做左旋操作,最后设置替换删除结点的结点为根结点;
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值