二叉排序树之红黑树
来源:互联网 发布:如何修改淘宝客佣金 编辑:程序博客网 时间:2024/05/22 11:04
红黑树的介绍
先来看下算法导论对R-BTree的介绍:
红黑树,一种二叉搜索树(BinarySearch Tree,BST),但在每个结点上增加一个存储位表示结点的颜色,可以是RED或BLACK。既然它是一种BST,它就具有BST的一般性质。
通过对任何一条从根结点到叶子结点的路径上结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。这里,必须要注意,红黑树不像AVL,是高度平衡的BST,红黑树不是绝对平衡的,它存在某结点的左右子树高度差大于二的情况。
红黑树上每个结点内一般含五个域:[parent,left,right,color,key],分别是指向父结点指针、指向左孩子结点指针、指向右孩子结点指针、结点颜色和结点键值。如果相应的指针域没有,则设为NIL。
红黑树的NIL结点,并非NULL指针,也不同于普通的树结点,它的颜色固定为BLACK,指针域中左右孩子通常固定指向NULL,可以不存在键值项和数据项。由于红黑树中的所有叶子结点的左右孩子和根结点的父结点指针都要指向NIL结点,如果为每个指针分配不同的NIL结点,必然造成内存浪费。因此,在红黑树的具体实现中,我们仅构造一个NIL结点,然后让所有叶子结点指向左右孩子的指针和根结点指向父结点的指针都来指向这个唯一的NIL结点。
注:此处叙述的叶子结点,不同于下文陈述红黑树性质的叶子结点即NIL结点,是具有实际意义的树内数据结点。
红黑树的性质
玩游戏,就得遵守游戏规则;人类社会的发展也伴随着制度法规的发展;就连咱们技术积累的撰写和评审也不例外,也有一定的标准或要求。要想参与进来,就得了解并接受规则!
红黑树也不例外,它有一套自己的规则,只是相对小众了些。接下来,让我们先了解一下。
一般的,红黑树,满足以下性质,即只有满足以下全部性质的树,我们才称之为红黑树:
1)每个结点要么是红的,要么是黑的;
2)根结点是黑的;
3)每个叶结点,即空结点(NIL)是黑的;
4)如果一个结点是红的,那么它的两个孩子都是黑的;
5)对每个结点,从该结点到其子孙结点的所有路径上都包含相同数目的黑结点。
下图所示,即是一颗红黑树。此图忽略了NIL结点。
当我们在对红黑树进行插入和删除等操作时,由于树发生了变化,那么就可能会违背红黑树的基本性质。为了保持红黑树的性质,我们可以通过对树进行旋转,即修改树中某些结点的颜色及指针指向,以达到插入、删除操作后,红黑树依然保持它特有的性质(即上文所述的五点性质)。
旋转
对树进行旋转,能保持不变的只有原树的有序搜索特性,而原树的红黑性质则不能保持,所以在红黑树的结点插入或删除后,需要采用旋转和颜色重涂来恢复树的红黑性质。红黑树的旋转,仅需要使用两种单旋,即左旋和右旋。具体详见上一篇技术积累《二叉搜索树之AVL树》,这里仅给出算法导论里左旋操作的伪码,不再重述。
LEFT-ROTATE(T, x) //T指代树的管理根结构,x为旋转根结点
1 y ← right[x] //Set y
2 right[x] ← left[y] //Turn y's left subtreeinto x's right subtree.
3 p[left[y]] ← x
4 p[y] ← p[x] //Link x's parent to y.
5 if p[x] = nil[T]
6 then root[T] ← y
7 elseif x = left[p[x]]
8 then left[p[x]] ← y
9 else right[p[x]] ← y
10 left[y] ← x //Put x on y'sleft.
11 p[x] ← y
红黑树的结点插入
算法导论给出的伪码如下:
RB-INSERT(T, z)
1 y ← nil[T]
2 x ← root[T]
3 while x ≠ nil[T] //注意是和指向NIL的指针比较
4 do y← x
5 if key[z] < key[x]
6 then x ← left[x]
7 else x ← right[x]
8 p[z] ← y //p[z]为查找到的新插入结点的父结点
9 if y = nil[T]
10 then root[T] ← z
11 else if key[z]< key[y]
12 then left[y] ← z
13 else right[y] ← z
14 left[z] ← nil[T]
15 right[z] ← nil[T]
16 color[z] ← RED //新插入结点颜色初始化为RED
17 RB-INSERT-FIXUP(T, z)
伪码1-13行与一般的BST结点插入算法过程无异:第1-8行是查找新插入结点的父结点,当然在第5-7行,我们可以考虑过滤键值相等的结点;伪码9-13是对新插入结点进行合理链接。伪码14-16是新插入结点的初始化。下面我们重点分析第17行,也就是红黑树的插入操作的平衡处理过程。
RB-INSERT-FIXUP(T, z),伪码如下所示:
1 while color[p[z]] = RED
2 do if p[z]= left[p[p[z]]]
3 then y ← right[p[p[z]]]
4 if color[y] = RED
5 then color[p[z]] ←BLACK ▹ Case 1
6 color[y] ←BLACK ▹ Case 1
7 color[p[p[z]]] ←RED ▹ Case 1
8 z ←p[p[z]] ▹Case 1
9 else if z = right[p[z]]
10 then z ←p[z] ▹Case 2
11 LEFT-ROTATE(T,z) ▹ Case 2
12 color[p[z]] ←BLACK ▹ Case 3
13 color[p[p[z]]] ←RED ▹ Case 3
14 RIGHT-ROTATE(T, p[p[z]]) ▹ Case 3
15 else (same as then clause
with "right" and "left" exchanged)
16 color[root[T]] ← BLACK
上面已经指出,新插入结点颜色为RED。因此,如果插入结点是根结点,红黑树的性质2会被破坏;如果插入结点的父结点是红色,则会破坏性质4。总而言之,插入一个新结点只会破坏性质2或性质4。
可采用的基本恢复策略为:其一,把违背红黑树性质的结点向上移,如果能移到根结点,那么就可以直接修改根结点来恢复红黑树的性质;其二,穷举所有违背红黑树性质的可能情况,进行归类处理。
1)插入的是根结点。
原树是空树,此情况只会违反性质2,直接把结点涂为黑色。
2)插入的结点的父结点是黑色。
红黑树性质保持,不做任何处理。
3)当前结点的父结点是红色,且祖父结点的另一个子结点(叔叔结点)是红色。
此时祖父一定存在且为黑色,否则插入前就已不是红黑树。此处,分为父结点是祖父结点的左孩子还是右孩子两种情况,由于对称性,我们只考虑父结点为祖父结点左孩子的情况,而当前结点是其父结点的左孩子还是右孩子这两种情况的处理方式相同。
对策如上述伪码5-8行的Case 1,即将当前结点的父结点和叔叔结点涂黑,祖父结点涂红,把当前结点指向祖父结点,从新的当前结点重新开始算法。
4)当前结点的父结点是红色,叔叔结点是黑色,当前结点是其父结点的右孩子。
对策如Case 2:当前节点的父结点做为新的当前结点,以新当前结点为旋转根结点进行左旋操作。则Case 2转化为Case 3。
5)当前结点的父结点是红色,叔叔结点是黑色,当前节点是其父结点的左孩子。
对策如Case 3:父结点变为黑色,祖父结点变为红色,再以祖父结点为旋转根结点进行右旋操作。Case 3处理后,由于color[p[z]]为BLACK,就会跳出整个while循环,平衡处理结束。
最后,将根结点涂成黑色,此即红黑树的平衡处理过程。可以看出,唯一需要循环下去的就是Case 1,故对于一个深度为N的红黑树,RB-INSERT-FIXUP(T, z)的算法复杂度为O(lgN),并且整个调整过程最多执行两次旋转,即执行了Case 2和Case 3。
红黑树的结点删除
算法导论给出的伪码如下:
RB-DELETE(T, z)
1 if left[z] = nil[T] or right[z] =nil[T]
2 then y ← z
3 else y ←TREE-SUCCESSOR(z)
4 if left[y] ≠ nil[T]
5 then x ← left[y]
6 else x ← right[y]
7 p[x] ← p[y]
8 if p[y] = nil[T]
9 then root[T] ← x
10 else if y = left[p[y]]
11 then left[p[y]] ← x
12 else right[p[y]] ← x
13 if y ≠ z
14 then key[z] ← key[y]
15 copy y's satellite data into z
16 if color[y] = BLACK
17 thenRB-DELETE-FIXUP(T, x)
18 return y
伪码1-15行即通常BST结点删除算法过程:第1-3行是根据删除结点的左右孩子情况,决定实际删除的结点y是待删结点本身还是其后继(或前驱)结点;第4-12分离y结点,并重新处理树结点的链接关系;第13-15行,若实际删除的是后继结点,把数据拷贝给待删结点,这是一个补丁,实际上可以紧接在第3行之后处理;第16-17行,即红黑树的删除操作的平衡处理过程,只有当实际删除结点的颜色为黑时,才调用RB-DELETE-FIXUP(T, x) 处理,因为若y非黑色,即为红色,则当y被删除时,红黑性质仍然保持:1)树中各结点的黑高度都没有变化,满足第5条性质;2)不存在两个相邻的红色结点,满足第4条性质;3)若y是红色的,就不可能是树的根结点,根结点继续保持原来的黑色,满足第2条性质;其他两条性质只是满足,不用说了。
在重点讨论红黑树删除操作的平衡处理过程之前,我先简述一下删除一个黑色结点对红黑树性质的影响,以便读者更好地理解后续的平衡处理过程。
当实际删除的结点y为黑色,会引起三点问题:
若y是树根结点,可能它的一个红色孩子结点变为新的根结点,这违背性质2;
若x和p[y](也即p[x])都为红色,则违背性质4;
结点y的删除,将使得任何原本经过y的路径比其它路径缺少一个黑色结点,即违背了性质5。可通过认定x有一重额外的黑色来解决该问题,则x成为二重黑结点或红黑复合结点,这个满足了性质5,却违背了性质1。x的颜色属性依然要么为红(若x为红黑复合结点),要么为黑(若x为二重黑结点),额外的一重黑色反映在程序算法中x的指向上。
因此,红黑树删除黑色结点归结为违背性质1,2和4。
算法导论给出的伪码如下:
RB-DELETE-FIXUP(T, x)
1 while x ≠ root[T] and color[x] = BLACK
2 do if x = left[p[x]]
3 then w ←right[p[x]]
4 if color[w] = RED
5 then color[w] ←BLACK ▹ Case 1
6 color[p[x]] ←RED ▹ Case 1
7 LEFT-ROTATE(T,p[x]) ▹ Case 1
8 w ←right[p[x]] ▹ Case 1
9 if color[left[w]] = BLACK and color[right[w]] = BLACK
10 then color[w] ←RED ▹ Case 2
11 x ←p[x] ▹ Case 2
12 else if color[right[w]] = BLACK
13 then color[left[w]] ←BLACK ▹ Case 3
14 color[w] ← RED ▹ Case 3
15 RIGHT-ROTATE(T, w) ▹ Case 3
16 w ← right[p[x]] ▹ Case 3
17 color[w] ←color[p[x]] ▹ Case 4
18 color[p[x]] ←BLACK ▹ Case 4
19 color[right[w]] ←BLACK ▹ Case 4
20 LEFT-ROTATE(T,p[x]) ▹ Case 4
21 x ← root[T] ▹ Case 4
22 else (same as then clause with"right" and "left" exchanged)
23 color[x] ← BLACK显然地,上述平衡处理过程可分为四种情况(以x为父结点的左孩子为例):
Case1:x的兄弟w是红色的。
5 then color[w] ←BLACK ▹ Case 1
6 color[p[x]] ←RED ▹ Case 1
7 LEFT-ROTATE(T,p[x]) ▹ Case 1
8 w ←right[p[x]] ▹ Case 1对策:改变结点w和父结点p[x]的颜色,再以p[x]为旋转根结点做一次左旋,红黑性质得以继续保持。x的新兄弟new w是旋转之前w的左孩子,必定为黑色。
所以,Case1转化成Case2或3、4。
Case2:x的兄弟w是黑色的,且w的俩个孩子都是黑色的。
10 then color[w] ←RED ▹ Case 2
11 x<-p[x] ▹ Case 2
对策:因为w也是黑色的,所以x和w都抽取一重黑色,上移给p[x],则w变为红。设置p[x]为新的x结点。
Case3:x的兄弟w是黑色的,w的左孩子是红色,w的右孩子是黑色。
13 then color[left[w]] ←BLACK ▹ Case 3
14 color[w] ←RED ▹ Case 3
15 RIGHT-ROTATE(T, w) ▹ Case 3
16 w ← right[p[x]] ▹ Case 3
对策:改变结点w和其左孩子left[w]的颜色,并以w为旋转根结点右旋,而红黑性质仍然得以保持。现在x的新兄弟w是一个有红色右孩子的黑结点,则Case3转化为Case4。Case4:x的兄弟w是黑色的,且w的右孩子为红色。
17 color[w] ←color[p[x]] ▹ Case 4
18 color[p[x]] ←BLACK ▹ Case 4
19 color[right[w]] ←BLACK ▹ Case 4
20 LEFT-ROTATE(T,p[x]) ▹ Case 4
21 x ←root[T] ▹ Case 4
对策:把p[x]的颜色赋给w,p[x]颜色涂为黑色,并以p[x]为旋转根结点进行左旋,则可去掉x的额外一重黑色,此举不破坏红黑性质。将x置为根后,循环结束。最后,将x涂成黑色,删除过程的平衡处理过程结束。可以看出,唯一需要循环下去的就是Case2,只需修改一个结点颜色和指针上移;而若进入Case1,3和4,经过固定几次颜色调整和至多3次旋转后,算法终止,故对于一个深度为N的红黑树,RB-DELETE-FIXUP(T,x)的算法复杂度依然为O(lgN)。
结束语
本文主要阐述了红黑树的插入删除操作,重点讨论了插入和删除操作对红黑树性质破坏后的恢复算法过程。文章最后给出具体的代码实现。
///////////////////////////////////////////////////////////////////////////////////////////////////////
以下源码已在VC6.0上验证通过。
/*****************************************************************
* 文件名:RBTree.c
* 需求: 实现RBTree的插入、删除、查找、遍历等基本功能
* 作者: 韩立忠 2012.04.28
****************************************************************/
/************************* 引入的头文件 *************************/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <assert.h>
/**************************** 宏定义 ****************************/
#define DEBUG_VERSION
#if defined DEBUG_VERSION
#define ASSERT(x) assert(x)
#else
#define ASSERT(x) NULL
#endif
/* 宏定义 */
#define INVAILD_VALUE (0xcccccccc)
#define STACK_SIZE (40)
/************************* 定义数据结构 *************************/
/* 函数返回值的枚举 */
enum
{
FALSE = 0,
TRUE = 1,
ERROR = INVAILD_VALUE
};
/* typedefs */
typedef int status_t;
typedef int key_t;
//typedef int data_t;
/* 定义RBTree结点颜色枚举类型 */
typedef enum COLOR_E
{
RED = 0, /* 红色 */
BLACK = 1 /* 黑色 */
}color_e;
/* 定义RBTree结点相对于父结点位置关系的枚举类型 */
typedef enum POS_E
{
NONE = INVAILD_VALUE,
LCHILD = 0, /* 标识本结点为父结点的左孩子 */
RCHILD = 1, /* 标识本结点为父结点的右孩子 */
DEGREE /* 标识树结点的度 */
}pos_e;
/* 定义RBTree的数据结点 */
typedef struct rbNode_s
{
struct rbNode_s *parent; /* 指向双亲的指针 */
struct rbNode_s *child[DEGREE]; /* 指向孩子的指针 */
color_e color; /* 结点颜色 */
}rbNode_t;
/* 用户定义的RBTree树数据结点 */
typedef struct myRbNode_s
{
void *parent; /* 指向双亲的指针 */
void *child[DEGREE]; /* 指向孩子的指针 */
color_e color; /* 结点颜色 */
key_t key; /* 键值项 */
//data_t data; /* 数据项 */
}myRbNode_t;
/************************* 定义回调函数 *************************/
typedef int (*nodeCmp_f)(void *, void *);
typedef void (*nodeCpy_f)(void *, void *);
typedef void (*nodeFree_f)(void *);
typedef void (*nodePrint_f)(void *);
/* 定义RBTree树指向根结点的Root结点 */
typedef struct rbTreeRoot_s
{
rbNode_t *root; /* 指向RBTree根结点的指针 */
rbNode_t *nil; /* RBTree的NIL结点 */
unsigned int cnt; /* RBTree结点总数 */
//unsigned char height; /* RBTree高度 */
nodeCmp_f nodeCmp; /* 结点键值比较函数 */
nodeCpy_f nodeCpy; /* 结点数据复制函数 */
nodeFree_f nodeFree; /* 结点内存释放函数 */
nodePrint_f nodePrint; /* 结点数据打印函数 */
}rbRoot_t;
/************************* 全局函数声明 *************************/
/* RBTree结点插入操作 */
status_t RBTree_insert(rbRoot_t *pRoot, rbNode_t *pNode);
/* RBTree结点删除操作 */
status_t RBTree_delete(rbRoot_t *pRoot, rbNode_t *pNode);
/* RBTree查找函数 */
rbNode_t *RBTree_search(rbRoot_t *pRoot, rbNode_t *pNode);
/* RBTree中序遍历函数 */
void RBTree_traverseInOrder(rbRoot_t *pRoot);
/* RBTree结点内存释放函数 */
void RBTree_free(rbRoot_t *pRoot);
/*-------------------------- 内部函数 --------------------------*/
/* 左旋/右旋函数 */
static void leftRotate(rbRoot_t *T, rbNode_t *x);
static void rightRotate(rbRoot_t *T, rbNode_t *y);
/* 查找指定树结点的直接前驱或后继结点函数 */
rbNode_t *findSuccessor(rbRoot_t *pRoot, rbNode_t *pNode);
/* 辅助查找函数 */
static rbNode_t *rbSearchAuxiliary(rbRoot_t *pRoot, rbNode_t *pNode, rbNode_t **ppSave);
/* RBTree管理根结点的初始化函数 */
static void RBTree_rootInit(rbRoot_t **ppRoot);
/* RBTree插入、删除操作的平衡处理函数 */
static void RBTree_insert_fixup(rbRoot_t *pRoot, rbNode_t *pNode);
static void RBTree_delete_fixup(rbRoot_t *pRoot, rbNode_t *pNode);
/*------------------------ 用户定义函数 ------------------------*/
rbNode_t *fillBuff(rbNode_t *pBuff, key_t *key); /* 数据填充函数 */
rbNode_t *encapNode(rbRoot_t *pRoot, key_t *key); /* 结点封装函数 */
int nodeCmp(void *pNode1, void *pNode2); /* 结点键值比较函数 */
void nodeCpy(void *pSNode, void *pDNode); /* 结点数据复制函数 */
void nodeFree(void *pNode); /* 结点内存释放函数 */
void nodePrint(void *pNode); /* 结点数据打印函数 */
/************************* 定义全局变量 *************************/
#define N 10000
//key_t a[10] = {3, 2, 1, 4, 5, 6, 7, 10, 9, 8};
key_t a[N] = {0};
/****************************************************************/
/**************************** 主函数 ****************************/
void test(void)
{
int i = 0;
rbRoot_t *pRoot = NULL;
myRbNode_t buff;
RBTree_rootInit(&pRoot);
for (i = 0; i < N; i++)
{
a[i] = i + 1;
}
for (i = 0; i < N; i++)
{
RBTree_insert(pRoot, encapNode(pRoot, &a[i]));
}
RBTree_traverseInOrder(pRoot);
for (i = N/20; i < N*3/4; i++)
{
RBTree_delete(pRoot, fillBuff((rbNode_t *)&buff, &a[i]));
}
RBTree_traverseInOrder(pRoot);
RBTree_free(pRoot);
return;
}
void main(void)
{
test();
return;
}
/****************************************************************/
/****************************************************************/
/* RBTree树的左旋处理函数 */
/*----------------------------------------
| |
(x) (y)
/ \ / \
a (y) ==> (x) c
/ \ / \
b c a b
----------------------------------------*/
static void leftRotate(rbRoot_t *T, rbNode_t *x)
{
rbNode_t *y = NULL;
pos_e pos = NONE;
if ((NULL == T) || (NULL == x))
{
ASSERT(0);
return;
}
y = x->child[RCHILD];
x->child[RCHILD] = y->child[LCHILD];
y->child[LCHILD]->parent = x;
y->parent = x->parent;
/* x为RBTree的根结点 */
if (x->parent == T->nil)
{
T->root = y;
}
/* x非RBTree的根结点 */
else
{
pos = (x == x->parent->child[LCHILD] ? LCHILD : RCHILD);
x->parent->child[pos] = y;
}
y->child[LCHILD] = x;
x->parent = y;
return;
}
/* RBTree树的右旋处理函数 */
/*------------------------------------------
| |
(y) (x)
/ \ / \
(x) c ==> a (y)
/ \ / \
a b b c
-------------------------------------------*/
static void rightRotate(rbRoot_t *T, rbNode_t *y)
{
rbNode_t *x = NULL;
pos_e pos = NONE;
if ((NULL == T) || (NULL == y))
{
ASSERT(0);
return;
}
x= y->child[LCHILD];
y->child[LCHILD] = x->child[RCHILD];
x->child[RCHILD]->parent = y;
x->parent = y->parent;
/* y为RBTree的根结点 */
if (y->parent == T->nil)
{
T->root = x;
}
/* y非RBTree的根结点 */
else
{
pos = (y== y->parent->child[LCHILD] ? LCHILD : RCHILD);
y->parent->child[pos] = x;
}
x->child[RCHILD] = y;
y->parent = x;
return;
}
/* 获取指定树结点的直接前驱或后继结点函数 */
rbNode_t *findSuccessor(rbRoot_t *pRoot, rbNode_t *pNode)
{
rbNode_t *pTmpNode = NULL;
rbNode_t *pNil = NULL;
if ((NULL == pRoot) || (NULL == pNode))
{
ASSERT(0);
return NULL;
}
pNil = pRoot->nil;
pTmpNode = pNode;
if (pTmpNode->child[LCHILD] != pNil) /* 优先找直接前驱结点 */
{
pTmpNode = pTmpNode->child[LCHILD];
while (pTmpNode->child[RCHILD] != pNil)
{
pTmpNode = pTmpNode->child[RCHILD];
}
}
else
{
if (pTmpNode->child[RCHILD] == pNil)
{
/* 出现错误调用,直接返回原结点 */
return pTmpNode;
}
pTmpNode = pTmpNode->child[RCHILD];
while (pTmpNode->child[LCHILD] != pNil)
{
pTmpNode = pTmpNode->child[LCHILD];
}
}
return pTmpNode;
}
/* RBTree查找结点函数 */
static rbNode_t *rbSearchAuxiliary(rbRoot_t *pRoot, rbNode_t *pNode, rbNode_t **ppSave)
{
rbNode_t *pTmpNode = NULL;
rbNode_t *pParent = NULL;
rbNode_t *pNil = NULL;
pos_e pos = NONE;
int rtnVal = 0;
if ((NULL == pRoot) || (NULL == pNode))
{
ASSERT(0);
return NULL;
}
pNil = pRoot->nil;
pTmpNode = pRoot->root;
pParent = pNil; /* 注意 */
while (pTmpNode != pNil)
{
pParent = pTmpNode;
rtnVal = pRoot->nodeCmp(pNode, pTmpNode);
if (0 == rtnVal)
{
/* 若树中存在相应结点,返回该结点 */
return pTmpNode;
}
pos = (rtnVal < 0 ? LCHILD : RCHILD);
pTmpNode = pTmpNode->child[pos];
}
if (ppSave != NULL)
{
*ppSave = pParent;
}
return NULL;
}
/* RBTree插入操作的平衡处理函数 */
static void RBTree_insert_fixup(rbRoot_t *pRoot, rbNode_t *pNode)
{
rbNode_t *pTmpNode = NULL;
rbNode_t *pParent = NULL;
rbNode_t *pUncle = NULL;
rbNode_t *pGrantpa = NULL;
if ((NULL == pRoot) || (NULL == pNode))
{
ASSERT(0);
return;
}
pTmpNode = pNode;
pParent = pTmpNode->parent;
while (RED == pParent->color)
{
pGrantpa = pParent->parent;
if (pParent == pGrantpa->child[LCHILD])
{
pUncle = pGrantpa->child[RCHILD];
/* Case1: 父节点P、叔叔节点U都为RED */
if (RED == pUncle->color)
{
pParent->color = BLACK;
pUncle->color = BLACK;
pGrantpa->color = RED;
pTmpNode = pGrantpa;
}
else
{
/* Case2: 父节点P是RED,叔叔节点U是黑色或NIL;
插入节点是P的RCHILD,而P又是其父节点G的LCHILD */
if (pTmpNode == pParent->child[RCHILD])
{
pTmpNode = pParent;
leftRotate(pRoot, pTmpNode);
}
/* Case3: 父节点P是RED,叔叔节点U是黑色或NIL;
插入节点是P的LCHILD,而P又是其父节点G的LCHILD */
pParent->color = BLACK;
pGrantpa->color = RED;
rightRotate(pRoot, pGrantpa);
}
}
else
{
pUncle = pGrantpa->child[LCHILD];
/* Case1: 父节点P、叔叔节点U都为RED */
if (RED == pUncle->color)
{
pParent->color = BLACK;
pUncle->color = BLACK;
pGrantpa->color = RED;
pTmpNode = pGrantpa;
}
else
{
/* Case2: 父节点P是RED,叔叔节点U是黑色或NIL;
插入节点是P的LCHILD,而P又是其父节点G的RCHILD */
if (pTmpNode == pParent->child[LCHILD])
{
pTmpNode = pParent;
rightRotate(pRoot, pTmpNode);
}
/* Case3: 父节点P是RED,叔叔节点U是黑色或NIL;
插入节点是P的RCHILD,而P又是其父节点G的RCHILD */
pParent->color = BLACK;
pGrantpa->color = RED;
leftRotate(pRoot, pGrantpa);
}
}
pParent = pTmpNode->parent;
}
ASSERT(pRoot->root != pRoot->nil);
pRoot->root->color = BLACK;
return;
}
/* RBTree删除操作的平衡处理函数 */
static void RBTree_delete_fixup(rbRoot_t *pRoot, rbNode_t *pNode)
{
rbNode_t *pTmpNode = NULL;
rbNode_t *pSibling = NULL; /* 兄弟结点 */
rbNode_t *pParent = NULL;
if ((NULL == pRoot) || (NULL == pNode))
{
ASSERT(0);
return;
}
pTmpNode = pNode; /* pTmpNode指向二重色结点 */
while ((pTmpNode != pRoot->root) && (BLACK == pTmpNode->color))
{
pParent = pTmpNode->parent;
if (pTmpNode == pParent->child[LCHILD])
{
pSibling = pParent->child[RCHILD];
/* Case1: 兄弟结点S是RED */
if (RED == pSibling->color)
{
pSibling->color = BLACK;
pParent->color = RED;
leftRotate(pRoot, pParent);
pSibling = pParent->child[RCHILD];
}
/* Case2: 兄弟结点S是BLACK,且S的俩孩子都是BLACK */
if ((BLACK == pSibling->child[LCHILD]->color)
&& (BLACK == pSibling->child[RCHILD]->color))
{
pSibling->color = RED;
pTmpNode = pParent;
continue;
}
/* Case3: 兄弟结点S是BLACK,且S的左孩子是RED,右孩子是BLACK */
else if (BLACK == pSibling->child[RCHILD]->color)
{
pSibling->child[LCHILD]->color = BLACK;
pSibling->color = RED;
rightRotate(pRoot, pSibling);
pSibling = pParent->child[RCHILD];
}
/* Case4: 兄弟结点S是BLACK,且S的右孩子是RED */
pSibling->color = pParent->color;
pParent->color = BLACK;
pSibling->child[RCHILD]->color = BLACK;
leftRotate(pRoot, pParent);
pTmpNode = pRoot->root;
}
else
{
pSibling = pParent->child[LCHILD];
/* Case1: 兄弟结点S是RED */
if (RED == pSibling->color)
{
pSibling->color = BLACK;
pParent->color = RED;
rightRotate(pRoot, pParent);
pSibling = pParent->child[LCHILD];
}
/* Case2: 兄弟结点S是BLACK,且S的俩孩子都是BLACK */
if ((BLACK == pSibling->child[LCHILD]->color)
&& (BLACK == pSibling->child[RCHILD]->color))
{
pSibling->color = RED;
pTmpNode = pParent;
continue;
}
/* Case3: 兄弟结点S是BLACK,且S的左孩子是BLACK,右孩子是RED */
else if (BLACK == pSibling->child[LCHILD]->color)
{
pSibling->child[RCHILD]->color = BLACK;
pSibling->color = RED;
leftRotate(pRoot, pSibling);
pSibling = pParent->child[LCHILD];
}
/* Case4: 兄弟结点S是BLACK,且S的左孩子是RED */
pSibling->color = pParent->color;
pParent->color = BLACK;
pSibling->child[LCHILD]->color = BLACK;
rightRotate(pRoot, pParent);
pTmpNode = pRoot->root;
}
}
pTmpNode->color = BLACK;
return;
}
/* RBTree根节点初始化函数 */
void RBTree_rootInit(rbRoot_t **ppRoot)
{
if (NULL == ppRoot)
{
ASSERT(0);
return;
}
*ppRoot = (rbRoot_t *)malloc(sizeof(rbRoot_t));
if (NULL == *ppRoot)
{
ASSERT(0);
return;
}
memset(*ppRoot, 0, sizeof(rbRoot_t));
/* 为NIL结点分配内存并置BLACK */
(*ppRoot)->nil = (rbNode_t *)malloc(sizeof(rbNode_t));
if (NULL == (*ppRoot)->nil)
{
ASSERT(0);
free(*ppRoot);
return;
}
memset((*ppRoot)->nil, 0, sizeof(rbNode_t));
(*ppRoot)->nil->color = BLACK;
(*ppRoot)->root = (*ppRoot)->nil; /* 注意 */
(*ppRoot)->nodeCmp = nodeCmp;
(*ppRoot)->nodeCpy = nodeCpy;
(*ppRoot)->nodeFree = nodeFree;
(*ppRoot)->nodePrint = nodePrint;
return;
}
/* RBTree插入结点函数 */
status_t RBTree_insert(rbRoot_t *pRoot, rbNode_t *pNode)
{
rbNode_t *pTmpNode = NULL;
rbNode_t *pParent = NULL; /* 插入结点的父结点 */
pos_e pos = NONE;
int rtnValue = INVAILD_VALUE;
if ((NULL == pRoot) || (NULL == pNode))
{
ASSERT(0);
return ERROR;
}
/* [1]查找结点插入位置 */
if (rbSearchAuxiliary(pRoot, pNode, &pParent) != NULL)
{
/* RBTree中已存在相应结点,则不再插入 */
pRoot->nodeFree(pNode);
return FALSE;
}
/* [2]插入结点 */
pNode->parent = pParent;
if (pParent == pRoot->nil) /* 插入结点为根结点 */
{
pRoot->root = pNode;
}
else /* 插入结点为非根结点 */
{
rtnValue = pRoot->nodeCmp(pNode, pParent);
ASSERT(rtnValue != 0);
pos = (rtnValue < 0 ? LCHILD : RCHILD);
pParent->child[pos] = pNode;
}
pRoot->cnt++;
/* [3]平衡处理 */
RBTree_insert_fixup(pRoot, pNode);
return TRUE;
}
/* RBTree删除结点函数 */
status_t RBTree_delete(rbRoot_t *pRoot, rbNode_t *pNode)
{
rbNode_t *pTmpNode = NULL; /* 指代二重色(RB/BB)结点 */
rbNode_t *pDelNode = NULL; /* 待删结点 */
rbNode_t *pNearNode = NULL; /* 邻近结点 */
rbNode_t *pNearParent = NULL; /* 邻近结点的父结点 */
rbNode_t *pNil = NULL;
pos_e pos = NONE;
if ((NULL == pRoot) || (NULL == pNode))
{
ASSERT(0);
return ERROR;
}
/* [1]查找待删结点位置 */
pDelNode = rbSearchAuxiliary(pRoot, pNode, NULL);
if (NULL == pDelNode)
{
/* 不存在相应结点,则直接返回 */
return FALSE;
}
/* [2]删除结点过程 */
/* [2]-1查找待删结点的直接前驱或后继结点(即邻近结点) */
pNil = pRoot->nil;
if ((pDelNode->child[LCHILD] == pNil) || (pDelNode->child[RCHILD] == pNil))
{
pNearNode = pDelNode;
}
else
{
pNearNode = findSuccessor(pRoot, pDelNode);
if (NULL == pNearNode)
{
ASSERT(0);
return ERROR;
}
}
/* [2]-2获取二重色结点 */
pos = (pNearNode->child[LCHILD] != pNil) ? LCHILD : RCHILD;
pTmpNode = pNearNode->child[pos];
/* [2]-3分离邻近结点或待删结点 */
pNearParent = pNearNode->parent;
pTmpNode->parent = pNearParent;///???///
if (pNearParent == pNil) /* 删除结点为根结点 */
{
pRoot->root = pTmpNode;
}
else
{
pos = (pNearNode == pNearParent->child[LCHILD] ? LCHILD : RCHILD);
pNearParent->child[pos] = pTmpNode;
}
if (pNearNode != pDelNode)
{
pRoot->nodeCpy(pNearNode, pDelNode);
}
pRoot->cnt--;
/* [3]平衡处理 */
if (BLACK == pNearNode->color)
{
RBTree_delete_fixup(pRoot, pTmpNode);
}
pRoot->nodeFree(pNearNode);
return TRUE;
}
/* RBTree查找函数(非递归方法) */
rbNode_t *RBTree_search(rbRoot_t *pRoot, rbNode_t *pNode)
{
return rbSearchAuxiliary(pRoot, pNode, NULL);
}
/* RBTree中序遍历函数 */
void RBTree_traverseInOrder(rbRoot_t *pRoot)
{
rbNode_t *stack[STACK_SIZE] = {0};
unsigned int top = 0;
rbNode_t *pNode = NULL;
rbNode_t *pNil = NULL;
if (NULL == pRoot)
{
ASSERT(0);
return;
}
pNode = pRoot->root;
pNil = pRoot->nil;
printf("Count:%10d\n", pRoot->cnt);
while ((pNode != pNil) || (top != 0))
{
while (pNode != pNil)
{
stack[top++] = pNode;
pNode = pNode->child[LCHILD];
}
pNode = stack[--top];
pRoot->nodePrint(pNode);
pNode = pNode->child[RCHILD];
}
printf("\n");
return;
}
/* 释放RBTree函数,包括根结点和数据结点,从左侧底开始释放 */
void RBTree_free(rbRoot_t *pRoot)
{
rbNode_t *stack[STACK_SIZE] = {0};
unsigned int top = 0;
pos_e pos = NONE;
rbNode_t *pNil = NULL;
rbNode_t *pNode = NULL;
rbNode_t *pParNode = NULL;
if (NULL == pRoot)
{
ASSERT(0);
return;
}
pNil = pRoot->nil;
pNode = pRoot->root;
while ((pNode != pNil) || (top != 0))
{
while (pNode != pNil)
{
stack[top++] = pNode;
pNode = pNode->child[LCHILD];
}
pNode = stack[--top];
ASSERT(pNode != pNil);
if (pNode->child[RCHILD] != pNil)
{
stack[top++] = pNode;
pNode = pNode->child[RCHILD];
continue;
}
/* 树结点的左右孩子都空,释放之 */
if (top != 0) /* 树的非根结点释放 */
{
pParNode = stack[--top];
pos = (pParNode->child[LCHILD] == pNode ? LCHILD : RCHILD);
pParNode->child[pos] = pNil;
pRoot->nodeFree(pNode);
pNode = pParNode;
}
else /* 树的根结点释放 */
{
ASSERT(pRoot->root == pNode);
pRoot->nodeFree(pNode);
pNode = pNil;
}
}
/* 最后释放树的管理根结点 */
free(pRoot->nil);
free(pRoot);
return;
}
/* 结点缓存填充数据函数(暂时仅填充key值) */
rbNode_t *fillBuff(rbNode_t *pBuff, key_t *key)
{
myRbNode_t *pNode = (myRbNode_t *)pBuff;
if ((NULL == pBuff) || (NULL == key))
{
ASSERT(0);
return NULL;
}
memset(pNode, 0, sizeof(myRbNode_t));
memcpy(&(pNode->key), key, sizeof(key_t));
//fill data
return (rbNode_t *)pNode;
}
/* 封装RBTree树结点,并初始化结点数据(暂不考虑data) */
rbNode_t *encapNode(rbRoot_t *pRoot, key_t *key)
{
myRbNode_t *pNode = NULL;
myRbNode_t *pNil = NULL;
if ((NULL == pRoot) || (NULL == key))
{
ASSERT(0);
return NULL;
}
pNode = (myRbNode_t *)malloc(sizeof(myRbNode_t));
if (NULL == pNode)
{
ASSERT(0);
return NULL;
}
memset(pNode, 0, sizeof(myRbNode_t));
pNil = (void *)pRoot->nil;
pNode->parent = pNil; /* 注意 */
pNode->child[LCHILD] = pNil;
pNode->child[RCHILD] = pNil;
pNode->color = RED;
memcpy(&(pNode->key), key, sizeof(key_t));
//data encap
return (rbNode_t *)pNode;
}
/* RBTree树结点键值比较函数 */
int nodeCmp(void *pNode1, void *pNode2)
{
myRbNode_t *pMyNode1 = (myRbNode_t *)pNode1;
myRbNode_t *pMyNode2 = (myRbNode_t *)pNode2;
int rtn = 0;
if ((NULL == pNode1) || (NULL == pNode2))
{
ASSERT(0);
return ERROR;
}
rtn = (pMyNode1->key < pMyNode2->key) ? \
(-1) : ((pMyNode1->key > pMyNode2->key) ? 1 : 0);
return rtn;
}
/* RBTree树结点数据复制函数 */
void nodeCpy(void *pSNode, void *pDNode)
{
myRbNode_t *pSMyNode = (myRbNode_t *)pSNode;
myRbNode_t *pDMyNode = (myRbNode_t *)pDNode;
if ((NULL == pSNode) || (NULL == pDNode))
{
ASSERT(0);
return;
}
memcpy(&(pDMyNode->key), &(pSMyNode->key), sizeof(key_t));
//memcpy(&(pDMyNode->data), &(pSMyNode->data), sizeof(data_t));
return;
}
/* RBTree树结点内存释放函数 */
void nodeFree(void *pNode)
{
myRbNode_t *pMyNode = (myRbNode_t *)pNode;
if (NULL == pNode)
{
ASSERT(0);
return;
}
free(pMyNode);
return;
}
/* RBTree树结点数据打印函数 */
void nodePrint(void *pNode)
{
myRbNode_t *pMyNode = (myRbNode_t *)pNode;
if (NULL == pNode)
{
ASSERT(0);
return;
}
printf("%d\t", pMyNode->key);
return;
}
/****************************************************************/
/* ************************* The End ************************** */
- 二叉排序树之红黑树
- 动态查找之二叉排序树
- 数据结构之二叉排序树
- 二叉排序树之删除节点
- 数据结构之(二叉排序树)
- 数据结构学习之二叉排序树
- 二叉排序树之递归陷阱
- 查找系列之二叉排序树
- 数据结构之二叉排序树
- 数据结构之二叉排序树
- 二叉排序树之删除操作
- 数据结构之二叉排序树
- 数据结构之二叉排序树
- 查找之二:二叉排序树
- 算法导论之二叉排序树
- 数据结构之二叉排序树
- 二叉排序树之Java实现
- JAVA数据结构之二叉排序树
- gdb与makefile
- Linux基础学习笔记之如何获取帮助
- HDU 5240 Exam(贪心水题)
- 导入第三方依赖库问题解决
- 【MPI学习1】简单MPI程序示例
- 二叉排序树之红黑树
- Java在终端中实时计算时使用float还是double?
- vmware虚拟机:ubuntu server安装vmware tools
- 例题6-1 UVa 210(deque 双端队列)
- [Ubuntu]网易云音乐libqt5libqgtk2缺失的解决方案
- A
- 手动加载DLL(PE文件)
- main函数的参数
- Java反射机制总结