数据结构 ——红黑树

红黑树

介绍

红黑树是一种自平衡的二叉查找树,是一种高效的查找树。它是由 Rudolf Bayer 于1972年发明,在当时被称为对称二叉 B 树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的红黑树。红黑树具有良好的效率,它可在 O(logN) 时间内完成查找、增加、删除等操作。因此,红黑树在业界应用很广泛,比如 Java 中的 TreeMap,JDK 1.8 中的 HashMap、C++ STL 中的 map 均是基于红黑树结构实现的。考虑到红黑树是一种被广泛应用的数据结构,所以我们很有必要去弄懂它。

​ 红黑树的定义如下:

  1. 节点是红色或黑色
  2. 根节点是黑色
  3. 所有叶子都是黑色( NIL 节点)
  4. 每个红色节点的两个子节点都是黑色(从每个叶子到根的所有路径上不能有两个连续的红色节点)
  5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点(定义为黑高)

​ 注意叶子节点 (NIL 节点不包含数据而只充当树在此结束的标志)。事实上,只要对红黑树的定义稍作修改,就能做到与 2-3 树一一对应,《算法》第四版中讲解的红黑树事实上就是与 2-3 树一一对应的,它规定红节点只能出现在左孩子的位置上。但是本文所讨论的红黑树还是和 2-3 树不同。

红黑树操作

旋转

​ 左旋是将某个节点旋转为其右孩子的左孩子,而右旋是将某个节点旋转为其左孩子的右孩子。需要注意的是,对于红树的旋转,需要交换旋转的两个节点的颜色,下图就是交换 C 和 P 的颜色。

颜色转换

​ 颜色转换即将子节点的颜色变为黑色,父节点的颜色变为红色。

插入

​ 红黑树的插入与二叉查找树的插入类似,但是又比它复杂一些,可以分为五种情况。对于插入而言,被插入的节点永远是红色的,因为如果被插入的节点是黑色的,那么经过插入节点的那条路径就会必其他路径的黑色节点是多1,不满足定义 5,无论插入的位置是什么,都需要进行调整以满足定义 5。故定义新插入的节点永远为红色。

情况一

​ 当插入节点是根节点,则将插入节点变为红色,作为根节点。

情况二

​ 当插入节点的父节点是黑色的,则直接插入就可以,不会破坏树的定义。

情况三

​ 当插入节点的父节点是红色的,叔节点是红色的,则插入之后需要进行颜色转换。这样一来,插入节点的祖父节点就会变成红色,可能会破坏树的定义,需要继续向上调整。

情况四

​ 当”插入节点“的父节点是红色的,叔节点是黑色的,且”插入“在左侧,需要进行如下调整。

​ 需要注意的是,这里的”插入节点“是加引号的,因此并不是真正意义上的插入。可以仔细想想,如果该位置的节点是直接插入的,那么 G 左右子树的黑高肯定就不一样了,这样就不满足定义 5。因此,节点 A 是由其他插入转化未而来的,如下图所示。图中的 PL 就是上图的 A。

情况五

​ 当”插入节点“的父节点是红色的,叔节点是黑色的,且”插入“在右侧,需要进行左旋操作,这样就与情况四一样了。

删除

​ 删除操作对红黑树来说更为复杂,与二叉查找树的删除类似,大体分以下三种情况。

  1. 被删除节点没有孩子节点:

    1. 如果删除的节点是红色的,直接删除即可。

    1. 如果删除的节点是黑色的,则需要进行调整。

  2. 被删除节点有一个孩子节点,这种情况下,孩子节点只有可能是红色的,父节点是黑色的。这样的情况也相对简单,用孩子节点替上被删除的节点,并将颜色改为黑色。不论红色节点是左节点还是右节点,删除都是一样的。

  1. 被删除节点有两个孩子节点,这时的删除方式就和二叉查找树很类似,需要找到这个节点的后继节点(前驱节点),然后将后继节点(前驱节点)的值复制到被删除的节点,问题转化为删除后继节点(前驱节点)。因为后继节点(前驱节点)只可能有一个孩子或者没有孩子,那么就是上述 1.1、1.2 和 2 的删除。

​ 对于上述 1.1 和 2 都没有特别困难,因此这里只讨论情况 1.2 。在被删除节点为黑色且无孩子节点的情况下,一共有四种情况(事实上按照排列组合有 16 种情况,由定义 4 排除不可能的,得到下面几种):

  • P为黑,S为黑,SL为黑,SR为黑
  • P为红,S为黑,SL为黑,SR为黑
  • P为黑,S为红,SR和SL为黑
  • P可红可黑,S为黑,SL和SR至少有一个红色

情况一

​ 被删除节点是黑色的,兄弟节点也是黑色的,父节点也是黑色的,兄弟节点的孩子节点也都是黑色的。此时删除节点 D,然后将 S 节点的颜色变为红色。这是通过 P 节点的路径的黑高就会少 1,需要继续向上调整直到根节点。

​ 事实上,这里的 DL DR SL SR 只能都是 NIL 节点,因此删除 D 后 P 也可以连接 DR。更一般的来说,DL DR SL SR 的黑高必须一致。

情况二

​ 被删除节点是黑色的,兄弟节点是黑色的,父节点是红色的,兄弟的孩子节点也都是黑色的。此时删除节点 D,调换 P 和 S 的颜色即可。

​ 事实上,这里的 DL DR SL SR 只能都是 NIL 节点,因此删除 D 后 P 也可以连接 DR。更一般的来说,DL DR SL SR 的黑高必须一致。

情况三

​ 被删除节点是黑色的,兄弟节点是红色的,它的兄弟节点的子节点都是黑色的。此时删除节点 D,需要以 P 为支点进行左旋,然后再以 P 为支点进行左旋,最后调换 SL 和 P 的颜色即可。

​ 事实上,这里的 DL DR 只能都是 NIL 节点,因此删除 D 后 P 也可以连接 DR。SL SR 只能是黑高为 2 的一颗子树。更一般的来说,DL DR 的黑高比 SL SR 的黑高少 1。

情况四

​ 被删除节点是黑色的,兄弟节点也是黑色的,但兄弟节点的左孩子是红色的,右孩子是黑色的。此时删除节点 D,需要以 P 为支点左旋,将 SR 变为黑色即可。

​ 事实上,这里的 DL DR SL 只能都是 NIL 节点,因此删除 D 后 P 也可以连接 DR。SR 是黑高为 1 的一颗子树。更一般的来说,DL DR SL SR 的黑高必须一致。

​ 被删除节点是黑色的,兄弟节点也是黑色的,但是兄弟节点的右孩子是红色的,左孩子是黑色的。则在情况可以转化为上述情况。此时删除节点 D,以 S 为支点右旋,即便为上述的情况。

​ 事实上,这里的 DL DR SR 只能都是 NIL 节点,因此删除 D 后 P 也可以连接 DR。SL 是黑高为 1 的一颗子树。更一般的来说,DL DR SL SR 的黑高必须一致。

​ 被删除节点是黑色的,兄弟节点也是黑色的,但是兄弟节点的右孩子是红色的,左孩子也是红色的。这种情况下,可以选择上述的两种方式之一即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值