红黑树

来源:互联网 发布:excel删除一列数据 编辑:程序博客网 时间:2024/06/07 07:23

红黑树的定义

红黑树和AVL树一样,也是一种平衡二叉树,红黑树是满足下列要求的二叉搜索树:

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

NOTE:
根据4,新增节点必须为红;根据3,新增节点之父节点必须为黑。

红黑树的分析

一、红黑二叉查找树
红黑树的出现功归于2_3查找树,红黑树和2_3查找树完全是等价的,但是2_3树的原理,插入过程比红黑树理解起来要容易的多,所以先学习2_3查找树然后从2_3查找树过渡到红黑树是一个更加科学的学习方式,不知道2_3查找树的同学不妨先去看我的这篇:2_3查找树

红黑二叉查找树完全由2_3查找树演变而来,2_3查找树更容易理解,但是对于很多编程语言来说,实现起来很难,所以发展出来了红黑树。

红黑二叉查找树背后的基本思想是用标准的二叉查找树(完全由2-结点构成)和一些额外的信息(替换3-结点)来表示2-3树。我们将书中的链接分为两种类型:红链接将两个2-结点连接起来构成一个3-结点,黑链接则是2-3树中的普通链接。确切的说,我们将3-结点表示为由一条左斜的红色链接(两个2-结点其中之一是另一个的左子结点)。
这里写图片描述
对于任意的2-3树,只要对结点进行转换,我们都可以立即派生出一棵对应的二叉查找树。我们将用这种方式表示2-3树的二叉查找树称为红黑二叉查找树(简称红黑树)。

红黑树的另一种定义是含有红黑链接并满足下列条件的二叉查找树:
1、红链接均为左链接。
2、没有任何一个节点同时和两个红链接相连。
3、该树是完美黑色平衡的,即任意空链接到根结点的路径上的黑链接数量相同。

我们根据我们重新理解的红黑二叉查找树来看看我们一开始对于红黑树下的定义:
1、每个结点不是红色就是黑色,这个很自然,2-3查找树中的所有结点不是2-结点就是3-结点。
2、根结点为黑色,红黑树中的红结点是指对应的2-3查找树中红色链接所指向的那个结点,也即是就父结点和子结点之间的链接是红色链接,那么这个子结点就是红结点,因为根结点没有父结点所以自然为黑结点。
3、如果结点为红,其子结点肯定为黑,将红黑树转换为2-3查找树,红黑树中的红结点和其父结点就构成了2-3查找树中的3-结点,如果一个结点为红,并且它的子结点也为红,那么这个结点和它的子结点构成了一个3-结点,并且这个结点和它的父结点也构成了一个3-结点,这时在2-3查找树中就会出现一个4-结点,不符合2-3结点的特点。
4、任一结点至NULL(树尾端)的任何路径,所含之黑结点数相同
这里写图片描述

红黑树既是二叉查找树,也是2-3树,因此具有这两个算法的优点:二叉查找树的简洁高效的查找方法和2-3树中高效的平衡插入算法。

二、红黑树插入中要用到的的基本操作
红黑树的插入操作要用到的最主要的基本操作就是左旋转和右旋转:
左旋转就是将红色的右链接转化为左链接,右旋转就是将将一个红色左链接转换为一个红色右链接。
这里写图片描述

三、红黑树的插入

向2-结点中插入新键

向一棵只含有一个2-结点的红黑树中插入一个新键有两种可能:
1、新键小于老键:只需要新增一个红色结点即可,新的红黑树和单个3-结点完全等价。
2、新键大于老键:这时候新增加的红色结点就会产生一条红色的右链接,需要使用root = rotateLeft(root);来将其旋转为红色左链接并修正根结点的链接,这样插入操作才算完成;
这两种情况的结果都是会得到一棵和单个3-结点等价的红黑树,其中含有两个键,一条红链接,树的黑链接高度为1。

向树底部的2-结点插入新键

向一棵红黑树中插入一个新键会在树的底部新增一个结点,但总是用红链接将新结点和它的父结点相连。
如果它的父结点是一个2-结点,那么刚才讨论的两种处理方法仍然适用。
如果指向新结点的是父结点的左链接,那么父结点就直接成为了一个3-结点;
如果指向新结点的是父结点的右链接,那么这就是一个错误的3-结点,但一次左旋转就能够修正它。如下图:
这里写图片描述

向一棵双键树(即一个3-结点)中插入新键

这种情况会产生三种子情况:新键小于树中的两个键,在两者之间,或是大于树中的两个键。每种情况都会产生一个同时链接到两条红链接的结点,我们的目标就是修正这一点。
1、如果新键大于原树中的两个键:那新键就会被连接到3-结点的右链接,此时树是平衡的,根结点为中间大小的键,它有两条红链接分别和较小和较大的结点相连。如果我们将两条链接的颜色都由红变黑,那么我们就得到了一棵由三个结点组成、高为2的平衡树,它正好对应一棵2-3树。
2、如果新键小于原树中的两个键,它会被连接到最左边的空链接,这样就产生了两条连续的红链接,此时我们只需要将上层的红链接右旋转即可得到第一种情况(中值键为根结点并和其他两个结点用红链接相连)。
3、如果新键介于原树中的两个键之间,这也会产生两条连续的红链接,一条红色左链接一条红色右链接,我们只需要将下层的红链接左旋转即可得到第二种情况(两条连续的红色左链接 )
这里写图片描述

向树底部的3-结点中插入新键

现在假设我们需要在树的底部的一个3-结点下加入一个新结点。前面讨论过的三种情况都会出现。如下图所示:
指向新结点的链接可能是3-结点的右链接(此时我们只需要转换颜色即可),
或是左链接(此时我们需要进行右旋转后再转换颜色),
或是中链接(此时我们需要先左旋转下层链接然后右旋转上层链接,最后再转换颜色)。

和双键树中的3-结点插入不同,向树底部的3-结点中插入新键时,颜色转换会使得中结点的链接变红,相当于将他送入了父结点。这意味着在父结点中继续插入一个新键,这是我们就需要使用相同的办法上溯解决这个问题。
将红链接在树中向上传递
在沿着插入点到根结点的路径向上移动时所经过的每个节点中顺序完成以下操作,我们就能完成插入操作:

如果右子结点是红色的而左子结点是黑色的,进行左旋转;如果左子结点是红色的且它的左子结点也是红色的,进行右旋转;如果左右子节点均为红色,进行颜色转换。

这里写图片描述

实现

红黑树的插入算法:
这里写图片描述

红黑树的插入轨迹:
这里写图片描述

原创粉丝点击