红黑树

来源:互联网 发布:java灵兽大乐斗 编辑:程序博客网 时间:2024/05/21 10:46

摘自数据结构(殷人昆版)

红黑树是这样的一棵二叉搜索树:树中的每个结点的颜色不是黑色就是红色。可以把一棵红黑树视为一棵扩充二叉树,用外部结点表示空指针。其特征如下:
1、 根结点和所有外部结点的颜色是黑色。
2、 从根结点到外部结点的途中没有连续的两个结点的颜色是红色。
3、 所有从根到外部结点的路径上都有相同数目的黑色结点。

从红黑树中任一结点x出发(不包括x结点),到达一个外部结点的任一路径上的黑结点个数叫做结点x的黑高度,亦称为结点的阶,记作bh(x)。红黑树的黑高度定义为其根结点的黑高度。


搜索的时间复杂度
二叉搜索树 > 红黑树 > AVL树

红黑树的插入:

1、 如果插入前是空树,那么新元素将成为根结点,根据特征1,根结点必须染成黑色。
2、 如果插入前树非空,若新结点被染成黑色,将违反红黑树的特征3,所有从根到外部结点的路径上的黑色结点个数不等。因此,新插入的结点将染成红色,但这又可能违反红黑树的特征2,出现连续的两个红色结点,因此需要重新平衡。
设新插入的结点为u,它的父结点分别是pu和gu。
若pu是黑色结点,平衡
若pu是红色结点,则出现连续两个红色结点的情形,这时还要考查pu的兄弟结点。
情况一
如果pu的兄弟结点gr是红色结点,此时结点pu的父结点gu是黑色结点它有两个红色子女结点。交换结点gu和它的子女结点的颜色,将可能破坏红黑树特征2,此时要以gu为基准调整结点,继续递归执行调整操作。

情况二
如果pu的兄弟结点gr是黑色结点,此时又分为两种情况
1、 u是pu的左子女,pu是gu的左子女,在这种情况下只要做一次右单旋,交换一下pu和gu的颜色,就可恢复红黑树的特征,并结束重新平衡过程。



2、 u是pu的右子女,pu是gu的左子女。在这种情况下做一个先左后右的又旋转,再交换一下u和gu的颜色,就可恢复红黑树的特征,结束重新平衡过程。




红黑树的删除
在红黑树中真正删除的结点应是叶结点或只有一个子女的结点。若设被删除结点为p,其唯一的子女为s。结点p被删除后,结点s取代了它的位置。
如果被删除结点p是红色的,删去它不存在问题。
如果被删除结点p是黑色的,则会破坏红黑树特征3的要求。
设u是被删结点p的唯一子女结点。如果u是红色结点,可以把结点u染成黑色,从而恢复红黑树的特征。
如果被删结点p是黑色结点,其唯一子女结点u也是黑色结点,就必须先将结点p摘下,将结点u链到其祖父结点g的下面。假设结点u成为结点g的右子女,v是u的左兄弟。根据v的颜色,分为以下两种情况:
情况一:结点v是黑色结点,若设结点v的左子女结点为w。根据w的颜色又需分两种情况讨论:
1、 结点w是红色结点,此时作一次右单旋转,将w,g染成黑色,v染成红色,就可以消除结点u的双重黑色,恢复红黑树的性质。

2、 结点w是黑色结点,还要看结点w的右兄弟结点r。根据结点的r的颜色,又要分两种情况:
a、 结点r是红色结点,可通过一次先左后右的双旋转,并将g染成黑色,就可以消除结点u的双重黑色,恢复红黑树的特性



旋转gvr

b、 结点r是黑色结点,这时还要看结点g的颜色。如果g是红色结点,只要交换结点g和其子女结点v的颜色就能恢复红黑树的特性。如果g是黑色结点,可做一次右单旋,将结点v上长虹并染成又重黑色,从而消除结点u的双重黑色,将双重黑色结点向根的方向移动




gvw的右旋

情况二:结点v是红色结点。考查v的右子女结点r。根据红黑树的特性2,r一定是黑色结点。再看结点r的左子女结点s。根据s的颜色,可分为两种情况:
1、 结点s是红色结点。通过一次先左后右双旋转,让r上长虹,使包含u的路径的黑高度增1,从而消除结点u的双重黑色,恢复红黑树的特性。

Gvr左右双旋

2、 结点s是黑色结点,再看结点s的右兄弟结点t。根据结点t的颜色又可分为两种情况:
a、 若结点t为红色结点,先以t为旋转轴,做左单旋转,以t替补r的位置;然后再以t为旋转轴,做一次先左后右的双旋转,可消除结点u的双重黑色,恢复红黑树的特性。

b、 若结点t为黑色结点,以v为旋转轴,做一次右单旋转,并改变v和r的颜色即可消除结点u的双重黑色,恢复红黑树的特性。
当结点u是结点g的左子女的情况与上面讨论的情况是镜像的,只要左右指针互换就可以了。


0 0