除了 AVL 树之外,另一个颇具历史并被广泛运用的平衡二叉搜索树是红黑树。同 AVL 树一样,红黑树的高度也近似为 O(logN),它是通过给节点标记上两种不同的颜色 (红、黑) 来实现此目的的。
- 模拟实现代码
概述
红黑树是在1972年由 Rudolf Bayer 发明的,当时被称为平衡二叉B树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的“红黑树”。
AVL 树中通过平衡因子将树的高度控制在近似 log(N),这种做法使得我们可以在 O(logN) 的时间复杂度内实现对树进行插入、查找等操做。而在红黑树中我们通过另一种规则对树进行限制,使得它的高度近似保持在 log(N) 。
以下是红黑树需满足的规则:
- 给每个节点增加一个域表示其颜色,它不是红色就是黑色;
- 根节点的颜色固定为黑;
- 如果某节点颜色为红,则其子节点必为黑(换句话说,不存在两个连续的红结点);
- 从任意节点到 NULL (NULL节点颜色设为黑) 的所有路径上所含的黑色节点个数相等 。
通过以上几条规则,限制了红黑树的最长路径长度不超过最短路径的两倍,同时也使得红黑树的高度近似为 logN ,即近似平衡。为什么呢?
我们假设一个极端情况:从根节点到某一叶子节点,其路径上全为黑色节点,个数为 N
, 那么该路径必为从根到所有叶子节点中最短的一条 (条件4限制每条路径黑色节点个数相等) ; 又由于条件3 (不存在两个连续的红色节点) 的限制,所以从根节点到叶子节点的路径中最长的一条必为一黑一红、一黑一红的情况,这样这条路径长度则为 2N
, 此时以达到满足红黑树规则情况下路径长度的极限 —— 最长路径为最短路径的两倍。
下面是 N ( 从根到 NULL ) 为 3 时红黑树的大致情况,可以看到最短路径为最右侧的那条,最长路径为最左侧的那条,它们正好是 2 倍关系,其它路径长度都应介于两者之间:
由于路径长度的特性,使得红黑树的高度近似为 log(N)。
插入节点
红黑树的插入操作类似于 AVL 树。
插入分为以下几步:
- 找到插入位置并插入;
- 检查是否破坏树的性质,如果是则旋转调整, 否则完成插入;
第一步寻找插入位置和普通搜索二叉树如出一辙,我们重点看第 2 步的调整动作。
按照插入节点位置的不同,如果要细分的话,可以分为 8 种不同情况,不过由于其中某些情况是对称的,它们的处理方法极为相似,故下面我们只分析其中四种情况。
为了方便讨论,先给一些特殊节点定义代名词。假设新节点为 cur
, 其父节点为 p
, 叔叔节点为 u
, 祖父节点为 g
, 祖父的祖父为 gg
。
新插入的节点的默认颜色有两种选择(红、黑)。若为黑,则由于性质 4 我们每次插入节点都会破坏红黑树性质,若为红,则只有 p
为红的情况下我们才需要对树进行调整,基于上述原因,我们默认新插入节点的颜色为红色。
- 情况 1 :
cur
为p
的左(右,左右都一样)p
为黑色;
最简单的一种情况 (方框内指的是另一种情况),此时插入节点后,没有破坏红黑树性质,则插入完成了。
- 情况 2:
cur
为p
的左(右,左右也一样)孩子,p
为红色,u
存在且为红色,g
为黑色;
这种情况,破坏了性质3(出现两个连续的红结点),我们只需对树进行简单的变色处理,并进行上溯即可;
如上图所示ÿ