-
本文的基础是红黑树 算法导论–红黑树
通过在基础的数据结构中添加一些附加信息,来扩张一种标准的数据结构,然后编写新的操作来支持所需要的应用。下面是介绍在红黑树的基础上扩张的数据结构。
1.动态顺序统计
动态顺序统计可以在O(lgn)时间内确定任何的顺序统计量(即在n个元素的集合中,能在O(lgn)的时间内确定第i小的元素),同时也可以在O(lgn)的时间内计算一个元素的秩(即它在中序遍历下的位置顺序)。
1 添加附加信息
结点x中加入x.size , size的大小为以x为根的子树(包含x本身)的内结数,即子树的大小。我们定义哨兵的size为0,如下图:
结点内,虚线上方为关键字key,下方为结点的size。
可以看出: x.size = x.left.size + x.right.size +1;01.
<code
class
=
" hljs d"
>
enum
colors{red,black};
//枚举类型
02.
typedef struct Node
03.
{
04.
struct Node * p;
05.
struct Node *left;
06.
struct Node *right;
07.
int
key;
08.
enum
colors color;
//颜色属性
09.
int
size;
//新添加的属性size
10.
}Node;</code>
2 修改基本操作
插入操作:
为了对子树规模的维护,需要在不影响插入和删除操作的渐进运行时间的前提下,修改基本的操作。
第一阶段:新节点的插入过程中,需要对从根到将要插入的位置过程中遍历的结点的size加1;
第二阶段:维护红黑树的左旋和右旋函数需要在最后添加以下语句:
1.
<code
class
=
" hljs avrasm"
>
/*左旋*/
2.
y.size = x.size;
3.
x.size = x.left.size + x.right.size +
1
;
4.
/*右旋*/
5.
x.size = y.size;
6.
y.size = y.left.size + y.right.size +
1
;</code>
删除操作:
第一阶段:如果要删除的结点z少于两个孩子,则从z到根T的过程遍历的结点size减1;如果要删除的结点z多于两个孩子,则从z的后继y处向上到T的过程中,遍历的结点size减1;
第二阶段:
也是同样在左右旋过程中,添加以上的语句;
插入操作和删除操作运行时间都是O(lgn).3 设计新的操作
1.给定秩的元素的检索
调用函数OS_Select(Node * x,int i)检索出在以x为根的子树中,第i小的关键字的结点。运行时间为O(lgn);01.
<code
class
=
" hljs lasso"
>Node * OS_Select(Node *x,
int
i)
02.
{
03.
int
r =x->left->size+
1
;
//计算以结点x为根的子树中顺序统计量r
04.
if
(i == r)
05.
return
x;
06.
else
if
(i < r)
07.
return
OS_Select(x->left,i);
//在x的左子树里继续递归查找
08.
else
09.
return
OS_Select(x->right,i-r);
//在x的右子树里继续递归查找
10.
}</code>
2.确定一个元素的秩
给定指向T中,结点x的指针,过程OS_Rank返回对T中序遍历对应的线性序中x的位置;运行时间为O(lgn)01.
<code
class
=
" hljs lasso"
>
int
OS_Rank(Node *T,Node * x)
02.
{
03.
int
r =x->left->size+
1
;
//计算以结点x为根的子树中顺序统计量r
04.
Node * y =x;
05.
while
(y != T)
//叠加到root根节点位置
06.
{
07.
if
(y == y->p->right)
//父节点的右子树输出在左子树和根之后,顺序统计量叠加
08.
{
09.
r=r+y->p->left->size+
1
;
10.
}
11.
y = y->p;
//若属于左子树,直接跳向上层
12.
}
13.
return
r;
14.
}</code>
4 完整代码
001.
<code
class
=
" hljs haskell"
>
/*
002.
CSDN 勿在浮砂筑高台
004.
算法导论--顺序统计量
005.
2015年5月20日
006.
*/
007.
#include <STDIO.H>
008.
#include <STDLIB.H>
009.
enum
colors{red,black};
//枚举类型
010.
typedef struct Node
011.
{
012.
struct Node * p;
013.
struct Node *left;
014.
struct Node *right;
015.
int
key;
016.
enum
colors color;
017.
int
size;
//添加附加信息size
018.
}Node;
019.
Node *T_NIL=NULL;
//建立全部变量 T_NIL
020.
021.
Node * Tree_Minimum(Node * T)
//找最小结点
022.
{
023.
while
(T->left != T_NIL)
024.
T=T->left;
025.
return
T;
026.
}
027.
void
Inorder_Tree_Walk(Node * T)
//中序遍历树T,输出
028.
{
029.
if
( T != T_NIL)
030.
{
031.
Inorder_Tree_Walk(T->left);
//递归其左孩子
032.
printf(
"%d"
,T->key);
//输出根的关键字
033.
if
(T->color ==
0
)
034.
{
035.
printf(
"-R"
);
036.
}
037.
else
038.
{
039.
printf(
"-B"
);
040.
}
041.
printf(
"-(%d) "
,T->size);
042.
Inorder_Tree_Walk(T->right);
//递归其右孩子
043.
}
044.
}
045.
void
Pre_Tree_Walk(Node * T)
//
046.
{
047.
if
( T != T_NIL)
048.
{
049.
printf(
"%d "
,T->key);
//输出根的关键字
050.
Pre_Tree_Walk(T->left);
//递归其左孩子
051.
Pre_Tree_Walk(T->right);
//递归其右孩子
052.
053.
}
054.
}
055.
056.
void
Left_Rotate(Node **T,Node * x)
//左旋
057.
{
058.
Node *y=x->right;
059.
060.
x->right =y->left;
061.
if
(y->left != T_NIL)
062.
y->left->p=x;
063.
y->p=x->p;
064.
if
(x->p==T_NIL)
065.
*T=y;
066.
else
if
(x == x->p->left)
067.
x->p->left = y;
068.
else
069.
x->p->right = y;
070.
y->left = x;
071.
x->p=y;
072.
073.
y->size = x->size;
//添加语句维护size
074.
x->size = x->left->size+x->right->size+
1
;
075.
}
076.
void
Right_Rotate(Node **T,Node * y)
//右旋
077.
{
078.
Node *x=y->left;
079.
080.
y->left =x->right;
081.
if
(x->right != T_NIL)
082.
x->right->p=y;
083.
x->p=y->p;
084.
if
(y->p==T_NIL)
085.
*T=x;
086.
else
if
(y == y->p->left)
087.
y->p->left = x;
088.
else
089.
y->p->right = x;
090.
x->right = y;
091.
y->p=x;
092.
093.
x->size = y->size;
//添加语句维护size
094.
y->size = y->left->size+y->right->size+
1
;
095.
}
096.
Node* RB_Insert_Fixup(Node *T,Node *z)
097.
{
098.
Node * y=NULL;
099.
while
( z->p->color == red)
//违反了性质4,迭代进行修正
100.
{
101.
if
(z->p == z->p->p->left)
102.
{
103.
y = z->p->p->right;
104.
if
( y->color == red)
// case 1 叔结点为红色
105.
{
106.
z->p->color = black;
//父节点涂黑
107.
y->color = black;
//叔结点涂黑
108.
z->p->p->color = red;
//祖结点涂红
109.
z = z->p->p;
//向上迭代,更新z的位置
110.
}
111.
else
if
( z == z->p->right)
//case 2 叔结点为黑色且z为双亲的右孩子
112.
{
113.
z = z->p;
114.
Left_Rotate(&T,z);
115.
z->p->color = black;
//case2 已转为 case3 继续处理
116.
z->p->p->color = red;
117.
Right_Rotate(&T,z->p->p);
// while循环终止
118.
}
119.
else
// case 3 叔结点为黑色且z为双亲的左孩子
120.
{
121.
z->p->color = black;
122.
z->p->p->color = red;
123.
Right_Rotate(&T,z->p->p);
// while循环终止
124.
}
125.
}
126.
127.
else
//对称处理
128.
{
129.
130.
y = z->p->p->left;
131.
if
( y->color == red)
// case 1 叔结点为红色
132.
{
133.
z->p->color = black;
134.
y->color = black;
135.
z->p->p->color = red;
136.
z = z->p->p;
137.
}
138.
139.
else
if
( z == z->p->left)
//case 2 叔结点为黑色且z为双亲的右孩子
140.
{
141.
z = z->p;
142.
Right_Rotate(&T,z);
143.
z->p->color = black;
144.
z->p->p->color = red;
145.
Left_Rotate(&T,z->p->p);
//
146.
}
147.
else
// case 3
148.
{
149.
z->p->color = black;
150.
z->p->p->color = red;
151.
Left_Rotate(&T,z->p->p);
152.
}
153.
154.
}
155.
}
156.
157.
T->color = black;
//保证不会违反性质2,对根节点涂黑
158.
return
T;
159.
}
160.
Node *RB_Insert(Node *Root,Node * z)
//红黑树插入,返回树的根
161.
{
162.
Node * y=T_NIL;
163.
Node * x=Root;
164.
while
( x != T_NIL)
//找到结点z要插入的位置
165.
{
166.
x->size+=
1
;
//插入过程中,遍历的结点size加1
167.
168.
y=x;
169.
if
(z->key < x->key)
170.
x = x->left;
171.
else
172.
x = x->right;
173.
}
174.
z->p = y;
175.
if
( y == T_NIL)
//插入第一个结点作为根节点的情况
176.
Root = z;
177.
else
if
(z->key < y->key)
178.
y->left = z;
179.
else
180.
y->right = z;
181.
182.
Root = RB_Insert_Fixup(Root,z);
//插入完毕后,对红黑树的颜色进行修正
183.
return
Root;
184.
}
185.
Node * Establish(
int
*A,
int
len)
//建立红黑树
186.
{
187.
Node * T,*node;
188.
int
i=
0
;
189.
node=NULL;
190.
T_NIL=(Node *)malloc(sizeof(Node));
//建立T_NIL结点
191.
T_NIL->p=NULL;
192.
T_NIL->left=NULL;
193.
T_NIL->right=NULL;
194.
T_NIL->key=-
1
;
195.
T_NIL->color=black;
196.
T_NIL->size=
0
;
197.
T=T_NIL;
198.
for
(i=
0
;i<len;i++)
199.
{
200.
node =(Node *)malloc(sizeof(Node));
201.
node->p =T_NIL;
202.
node->left=T_NIL;
203.
node->right=T_NIL;
204.
node->key=A[i];
205.
node->color=red;
206.
node->size=
1
;
207.
T=RB_Insert(T,node);
208.
}
209.
return
T;
210.
}
211.
212.
void
RB_Transplant(Node **T,Node * u,Node * v)
//结点替代函数
213.
{
214.
if
(u->p == T_NIL)
215.
*T = v;
216.
else
if
(u == u->p->left)
217.
u->p->left = v;
218.
else
219.
u->p->right = v;
220.
v->p = u->p;
//此处赋值无条件,v如果是T_NIL也要进行赋值
221.
}
222.
void
RB_Delete_Fixup(Node * T,Node * x)
223.
{
224.
Node *w=NULL;
225.
while
( x != T && x->color == black)
//循环迭代处理
226.
{
227.
if
( x == x->p->left )
228.
{
229.
w = x->p->right;
230.
if
(w->color == red)
// case 1 ------> case 2 , case 3 ,case 4
231.
{
232.
w->color = black;
233.
x->p->color =red;
234.
Left_Rotate(&T,x->p);
235.
w = x->p->right;
236.
}
237.
if
( w->left->color == black && w->right->color == black )
//case 2 ------>go on / stop
238.
{
239.
w->color = red;
240.
x = x->p;
241.
}
242.
else
if
( w->right->color == black)
// case 3 ---->case 4---->stop
243.
{
244.
w->left->color = black;
245.
w->color =red ;
246.
Right_Rotate(&T,w);
247.
248.
w = x->p->right ;
//转成case 4处理
249.
w->color = x->p->color;
250.
x->p->color = black;
251.
w->right->color = black;
252.
Left_Rotate(&T,x->p);
253.
x = T;
254.
}
255.
else
// case 4 ------------------->stop
256.
{
257.
w->color = x->p->color;
258.
x->p->color = black;
259.
w->right->color = black;
260.
Left_Rotate(&T,x->p);
261.
x = T;
262.
}
263.
}
264.
else
265.
{
266.
w = x->p->left;
267.
if
(w->color == red)
// case 1 ------> case 2 , case 3 ,case 4
268.
{
269.
w->color = black;
270.
x->p->color =red;
271.
Right_Rotate(&T,x->p);
272.
w = x->p->left;
273.
}
274.
if
( w->right->color == black && w->left->color == black )
//case 2 ------>go on/stop
275.
{
276.
w->color = red;
277.
x = x->p;
278.
}
279.
else
if
( w->left->color == black)
// case 3 -----> case 4----->stop
280.
{
281.
w->right->color = black;
282.
w->color =red ;
283.
Left_Rotate(&T,w);
284.
285.
w = x->p->left ;
//转成case 4处理
286.
w->color = x->p->color;
287.
x->p->color = black;
288.
w->left->color = black;
289.
Right_Rotate(&T,x->p);
290.
x = T;
291.
}
292.
else
// case 4 -------------->stop
293.
{
294.
w->color = x->p->color;
295.
x->p->color = black;
296.
w->left->color = black;
297.
Right_Rotate(&T,x->p);
298.
x = T;
299.
}
300.
}
301.
}
302.
303.
x->color = black;
//可能由case2退出,那把x涂黑即可,见分析!也可能有case4退出,把根节点涂黑
304.
}
305.
Node * RB_Delete(Node *T ,Node *z)
306.
{
307.
308.
Node * x =NULL;
309.
Node * y =z;
310.
Node *temp=y->p;
311.
enum
colors y_original_color = y->color;
//记录下删除前z的颜色
312.
if
( z->left == T_NIL)
//左子树不存在的情况
313.
{
314.
x = z->right;
315.
RB_Transplant(&T,z,z->right);
316.
}
317.
else
if
( z->right == T_NIL)
//右子树不存在
318.
{
319.
x = z->left;
320.
RB_Transplant(&T,z,z->left);
321.
}
322.
else
//左右都存在的情况
323.
{
324.
y = Tree_Minimum(z->right);
//找到后继y
325.
temp=y->p;
326.
y_original_color = y->color;
//记录下y转移前的颜色
327.
x = y->right;
328.
if
( y->p == z)
//如果y是z的子结点
329.
{
330.
x->p = y;
331.
}
332.
else
333.
{
334.
RB_Transplant(&T,y,y->right);
//如果y不是z的子结点,用y的右子树代替y的位置
335.
y->right = z->right;
336.
y->right->p = y;
337.
}
338.
RB_Transplant(&T,z,y);
//y替代z的位置 ,不论y是不是T_NIL
339.
y->left = z->left;
340.
y->left->p = y;
341.
y->color = z->color;
//把y的颜色改成z的颜色
342.
343.
y->size =y->left->size+y->right->size+
1
;
344.
}
345.
346.
while
(temp != T_NIL)
//从删除的位置或后继的位置向上遍历size--,直到根节点为止
347.
{
348.
temp->size--;
349.
temp = temp->p;
350.
}
351.
352.
353.
354.
if
( y_original_color == black)
//判断y的颜色,若为黑色,需要修复
355.
RB_Delete_Fixup(T,x);
356.
return
T;
357.
}
358.
359.
Node * Tree_Search(Node *T ,
int
k)
//寻找数k是否在树中,且返回数k的地址
360.
{
361.
362.
while
(T !=T_NIL && T->key != k)
363.
{
364.
if
( k < T->key)
365.
T=T->left;
366.
else
367.
T=T->right;
368.
}
369.
370.
if
( T == T_NIL)
371.
{
372.
return
NULL;
373.
}
374.
375.
else
376.
{
377.
return
T;
378.
}
379.
380.
}
381.
Node * OS_Select(Node *x,
int
i)
//确定以x为根节点的子树,第i小的关键字
382.
{
383.
int
r =x->left->size+
1
;
384.
if
(i == r)
385.
return
x;
386.
else
if
(i < r)
387.
return
OS_Select(x->left,i);
388.
else
389.
return
OS_Select(x->right,i-r);
390.
}
391.
int
OS_Rank(Node *T,Node * x)
//确定x在树T中序遍历中的位置顺序
392.
{
393.
int
r =x->left->size+
1
;
394.
Node * y =x;
395.
while
(y != T)
396.
{
397.
if
(y == y->p->right)
398.
{
399.
r=r+y->p->left->size+
1
;
400.
}
401.
y = y->p;
402.
}
403.
return
r;
404.
}
405.
void
main()
406.
{
407.
int
A[]={
2
,
5
,
1
,
6
,
3
,
8
,
4
,
9
,
7
};
408.
409.
int
length = sizeof(A)/sizeof(A[
0
]);
//数组A的长度
410.
Node *T =Establish(A,length);
//建立红黑树,返回根节点T
411.
412.
printf(
"中序遍历:\n"
);
413.
Inorder_Tree_Walk(T);printf(
"\n"
);
//中序遍历输出
414.
415.
printf(
"先序遍历:\n"
);
//先序遍历输出
416.
Pre_Tree_Walk(T);printf(
"\n"
);
417.
418.
printf(
"__%d__\n"
,OS_Select(T,
5
)->key);
419.
printf(
"--%d--\n"
,OS_Rank(T,Tree_Search(T,
3
)));
420.
421.
printf(
"-----------删除操作后-------------\n"
);
422.
423.
T=RB_Delete(T,Tree_Search(T,
2
));
424.
T=RB_Delete(T,Tree_Search(T,
5
));
425.
T=RB_Delete(T,Tree_Search(T,
7
));
426.
T=RB_Delete(T,Tree_Search(T,
4
));
427.
printf(
"中序遍历:\n"
);
428.
Inorder_Tree_Walk(T);
429.
printf(
"\n"
);
430.
431.
printf(
"先序遍历:\n"
);
432.
Pre_Tree_Walk(T);
433.
434.
printf(
"\n"
);
435.
}</code>
2.区间树
区间树是通过扩张红黑树来构成由区间构成的动态集合。结点的属性由一个关键字key变成了一个区间。
1.添加附加信息
添加区间信息INT,INT结构包含区间的左右端点。还包含Max属性,它是以自身为根的子树中所有的区间的端点最大值。(上图中虚线下方)
01.
<code
class
=
" hljs d"
>
enum
colors{red,black};
//枚举类型
02.
struct Interval
//区间
03.
{
04.
int
low;
05.
int
high;
06.
};
07.
typedef struct Node
08.
{
09.
struct Node * p;
10.
struct Node *left;
11.
struct Node *right;
12.
enum
colors color;
13.
//添加的属性
14.
struct Interval INT;
//存储结点区间信息
15.
int
Max;
//以结点为根的所有区间端点的最大值
16.
}Node;</code>
2.修改基本操作
修改红黑树的插入和删除操作维添加的信息,都能保证在O(lgn)的时间内完成;
1.插入操作:
第一步:由于区间树采用区间左端点作为关键字进行插入,遍历时通过比较INT.low的方式插入;插入前令Max=high,插入时从根节点开始遍历到要插入的位置,把遍历的结点的Max与新添加的结点z的Max进行比较,如果z.Max>x.Max ,更新结点的x.Max=z.Max01.
<code
class
=
" hljs lasso"
>Node *Interval_Insert(Node *Root,Node * z)
//红黑树插入,返回树的根
02.
{
03.
Node * y=T_NIL;
04.
Node * x=Root;
05.
while
( x != T_NIL)
//找到结点z要插入的位置
06.
{
07.
if
( z->Max > x->Max)
//比较新插入的结点z与结点x的Max大小;
08.
{
09.
x->Max = z->Max;
10.
}
11.
y=x;
12.
if
(z->INT.low < x->INT.low)
13.
x = x->left;
14.
else
15.
x = x->right;
16.
}
17.
z->p = y;
18.
if
( y == T_NIL)
//插入第一个结点作为根节点的情况
19.
Root = z;
20.
else
if
(z->INT.low < y->INT.low)
21.
y->left = z;
22.
else
23.
y->right = z;
24.
25.
Root = Interval_Insert_Fixup(Root,z);
//插入完毕后,对红黑树的颜色进行修正
26.
return
Root;
27.
}</code>
第二步:由于左旋右旋会破坏区间的性质,在函数代码后添加更新信息
01.
<code
class
=
" hljs lasso"
>
void
Left_Rotate(Node **T,Node * x)
//左旋
02.
{
03.
Node *y=x->right;
04.
05.
x->right =y->left;
06.
if
(y->left != T_NIL)
07.
y->left->p=x;
08.
y->p=x->p;
09.
if
(x->p==T_NIL)
10.
*T=y;
11.
else
if
(x == x->p->left)
12.
x->p->left = y;
13.
else
14.
x->p->right = y;
15.
y->left = x;
16.
x->p=y;
17.
18.
y->Max = x->Max;
//添加语句维护Max
19.
x->Max = GetMax(x->left->Max,x->right->Max,x->INT.high);
20.
}
21.
void
Right_Rotate(Node **T,Node * y)
//右旋
22.
{
23.
Node *x=y->left;
24.
25.
y->left =x->right;
26.
if
(x->right != T_NIL)
27.
x->right->p=y;
28.
x->p=y->p;
29.
if
(y->p==T_NIL)
30.
*T=x;
31.
else
if
(y == y->p->left)
32.
y->p->left = x;
33.
else
34.
y->p->right = x;
35.
x->right = y;
36.
y->p=x;
37.
38.
x->Max = y->Max;
//添加语句维护Max
39.
y->Max = GetMax(y->left->Max,y->right->Max,y->INT.high);
40.
}</code>
2.删除操作
第一步:被删除的结点z可能会影响整个区间树的性质,如果结点z少于两个孩子,则沿着z上升到根节点为止,对树重新更新维护;如果有两个孩子则从后继出发,进行维护;
1.
<code
class
=
" hljs lasso"
>
while
( temp != T_NIL )
//从要删除的结点或其后继开始向上修复区间树
2.
{
3.
temp->Max = GetMax(temp->left->Max,temp->right->Max,temp->INT.high);
4.
temp = temp->p;
//每次一层,至多lgn层
5.
}</code>
第二步:同上,也是在左旋右旋函数后添加代码。
3.设计新的操作
判断给定的一个区间i位于区间树的哪个位置。区间之间的关系:
a重叠的情况;b、c不重叠的情况
不重叠的情况用代码表示为1.
<code
class
=
" hljs haskell"
>x->INT.high < i->low
2.
x->INT.low > i->high</code>
如果存在区间与i重叠则返回结点的位置,否则返回T_NIL
01.
<code
class
=
" hljs lasso"
>Node * Interval_Search(Node *T ,struct Interval *i)
//寻找数k是否在树中,且返回数k的地址
02.
{
03.
Node * x = T;
04.
while
(x != T_NIL && ((x->INT.high < i->low)||(x->INT.low > i->high)))
//不重叠
05.
{
06.
if
(x->left != T_NIL && x->left->Max >= i->low)
//在其左子树中搜索
07.
{
08.
x = x->left;
09.
}
10.
else
11.
{
12.
x = x->right;
13.
}
14.
}
15.
16.
return
x;
17.
}</code>
每次迭代都是一层,至多lgn层;所以耗时O(lgn)的时间
4.完整代码
001.
<code
class
=
" hljs haskell"
>
/*
002.
CSDN 勿在浮砂筑高台
004.
算法导论--区间树
005.
2015年5月20日
006.
*/
007.
#include <STDIO.H>
008.
#include <STDLIB.H>
009.
enum
colors{red,black};
//枚举类型
010.
struct Interval
//区间
011.
{
012.
int
low;
013.
int
high;
014.
};
015.
typedef struct Node
016.
{
017.
struct Node * p;
018.
struct Node *left;
019.
struct Node *right;
020.
enum
colors color;
021.
//添加的属性
022.
struct Interval INT;
//存储结点区间信息
023.
int
Max;
//以结点为根的所有区间端点的最大值
024.
}Node;
025.
Node *T_NIL=NULL;
//建立全部变量 T_NIL
026.
027.
int
GetMax(
int
a,
int
b,
int
c)
//返回a,b,c最大值
028.
{
029.
return
a>b?(a>c?a:c):(b>c?b:c);
030.
}
031.
Node * Tree_Minimum(Node * T)
//找最小结点
032.
{
033.
while
(T->left != T_NIL)
034.
T=T->left;
035.
return
T;
036.
}
037.
void
Inorder_Tree_Walk(Node * T)
//中序遍历树T,输出
038.
{
039.
if
( T != T_NIL)
040.
{
041.
Inorder_Tree_Walk(T->left);
//递归其左孩子
042.
printf(
"%d"
,T->INT.low);
//输出根的关键字
043.
if
(T->color ==
0
)
044.
{
045.
printf(
"-R(%d) "
,T->Max);
046.
}
047.
else
048.
{
049.
printf(
"-B(%d) "
,T->Max);
050.
}
051.
Inorder_Tree_Walk(T->right);
//递归其右孩子
052.
}
053.
}
054.
void
Pre_Tree_Walk(Node * T)
//
055.
{
056.
if
( T != T_NIL)
057.
{
058.
printf(
"%d "
,T->INT.low);
//输出根的关键字
059.
Pre_Tree_Walk(T->left);
//递归其左孩子
060.
Pre_Tree_Walk(T->right);
//递归其右孩子
061.
062.
}
063.
}
064.
065.
void
Left_Rotate(Node **T,Node * x)
//左旋
066.
{
067.
Node *y=x->right;
068.
069.
x->right =y->left;
070.
if
(y->left != T_NIL)
071.
y->left->p=x;
072.
y->p=x->p;
073.
if
(x->p==T_NIL)
074.
*T=y;
075.
else
if
(x == x->p->left)
076.
x->p->left = y;
077.
else
078.
x->p->right = y;
079.
y->left = x;
080.
x->p=y;
081.
082.
y->Max = x->Max;
//添加语句维护Max
083.
x->Max = GetMax(x->left->Max,x->right->Max,x->INT.high);
084.
}
085.
void
Right_Rotate(Node **T,Node * y)
//右旋
086.
{
087.
Node *x=y->left;
088.
089.
y->left =x->right;
090.
if
(x->right != T_NIL)
091.
x->right->p=y;
092.
x->p=y->p;
093.
if
(y->p==T_NIL)
094.
*T=x;
095.
else
if
(y == y->p->left)
096.
y->p->left = x;
097.
else
098.
y->p->right = x;
099.
x->right = y;
100.
y->p=x;
101.
102.
x->Max = y->Max;
//添加语句维护Max
103.
y->Max = GetMax(y->left->Max,y->right->Max,y->INT.high);
104.
}
105.
Node* Interval_Insert_Fixup(Node *T,Node *z)
106.
{
107.
Node * y=NULL;
108.
while
( z->p->color == red)
//违反了性质4,迭代进行修正
109.
{
110.
if
(z->p == z->p->p->left)
111.
{
112.
y = z->p->p->right;
113.
if
( y->color == red)
// case 1 叔结点为红色
114.
{
115.
z->p->color = black;
//父节点涂黑
116.
y->color = black;
//叔结点涂黑
117.
z->p->p->color = red;
//祖结点涂红
118.
z = z->p->p;
//向上迭代,更新z的位置
119.
}
120.
else
if
( z == z->p->right)
//case 2 叔结点为黑色且z为双亲的右孩子
121.
{
122.
z = z->p;
123.
Left_Rotate(&T,z);
124.
z->p->color = black;
//case2 已转为 case3 继续处理
125.
z->p->p->color = red;
126.
Right_Rotate(&T,z->p->p);
// while循环终止
127.
}
128.
else
// case 3 叔结点为黑色且z为双亲的左孩子
129.
{
130.
z->p->color = black;
131.
z->p->p->color = red;
132.
Right_Rotate(&T,z->p->p);
// while循环终止
133.
}
134.
}
135.
136.
else
//对称处理
137.
{
138.
139.
y = z->p->p->left;
140.
if
( y->color == red)
// case 1 叔结点为红色
141.
{
142.
z->p->color = black;
143.
y->color = black;
144.
z->p->p->color = red;
145.
z = z->p->p;
146.
}
147.
148.
else
if
( z == z->p->left)
//case 2 叔结点为黑色且z为双亲的右孩子
149.
{
150.
z = z->p;
151.
Right_Rotate(&T,z);
152.
z->p->color = black;
153.
z->p->p->color = red;
154.
Left_Rotate(&T,z->p->p);
//
155.
}
156.
else
// case 3
157.
{
158.
z->p->color = black;
159.
z->p->p->color = red;
160.
Left_Rotate(&T,z->p->p);
161.
}
162.
163.
}
164.
}
165.
166.
T->color = black;
//保证不会违反性质2,对根节点涂黑
167.
return
T;
168.
}
169.
Node *Interval_Insert(Node *Root,Node * z)
//红黑树插入,返回树的根
170.
{
171.
Node * y=T_NIL;
172.
Node * x=Root;
173.
while
( x != T_NIL)
//找到结点z要插入的位置
174.
{
175.
if
( z->Max > x->Max)
//比较新插入的结点z与结点x的Max大小;
176.
{
177.
x->Max = z->Max;
178.
}
179.
y=x;
180.
if
(z->INT.low < x->INT.low)
181.
x = x->left;
182.
else
183.
x = x->right;
184.
}
185.
z->p = y;
186.
if
( y == T_NIL)
//插入第一个结点作为根节点的情况
187.
Root = z;
188.
else
if
(z->INT.low < y->INT.low)
189.
y->left = z;
190.
else
191.
y->right = z;
192.
193.
Root = Interval_Insert_Fixup(Root,z);
//插入完毕后,对红黑树的颜色进行修正
194.
return
Root;
195.
}
196.
Node * Establish(
int
A[][
2
],
int
len)
//建立红黑树
197.
{
198.
Node * T,*node;
199.
int
i=
0
;
200.
node=NULL;
201.
T_NIL=(Node *)malloc(sizeof(Node));
//建立T_NIL结点
202.
T_NIL->p=NULL;
203.
T_NIL->left=NULL;
204.
T_NIL->right=NULL;
205.
T_NIL->INT.low=-
1
;
206.
T_NIL->color=black;
207.
T_NIL->Max=
0
;
208.
T=T_NIL;
209.
for
(i=
0
;i<len;i++)
210.
{
211.
node =(Node *)malloc(sizeof(Node));
212.
node->p =T_NIL;
213.
node->left=T_NIL;
214.
node->right=T_NIL;
215.
node->INT.low=A[i][
0
];
//以INT.low左作为关键字
216.
node->INT.high=A[i][
1
];
217.
node->Max = A[i][
1
];
218.
node->color=red;
219.
T=Interval_Insert(T,node);
220.
}
221.
return
T;
222.
}
223.
224.
void
RB_Transplant(Node **T,Node * u,Node * v)
//结点替代函数
225.
{
226.
if
(u->p == T_NIL)
227.
*T = v;
228.
else
if
(u == u->p->left)
229.
u->p->left = v;
230.
else
231.
u->p->right = v;
232.
v->p = u->p;
//此处赋值无条件,v如果是T_NIL也要进行赋值
233.
}
234.
Node* Interval_Delete_Fixup(Node * T,Node * x)
235.
{
236.
Node *w=NULL;
237.
while
( x != T && x->color == black)
//循环迭代处理
238.
{
239.
if
( x == x->p->left )
240.
{
241.
w = x->p->right;
242.
if
(w->color == red)
// case 1 ------> case 2 , case 3 ,case 4
243.
{
244.
w->color = black;
245.
x->p->color =red;
246.
Left_Rotate(&T,x->p);
247.
w = x->p->right;
248.
}
249.
if
( w->left->color == black && w->right->color == black )
//case 2 ------>go on / stop
250.
{
251.
w->color = red;
252.
x = x->p;
253.
}
254.
else
if
( w->right->color == black)
// case 3 ---->case 4---->stop
255.
{
256.
w->left->color = black;
257.
w->color =red ;
258.
Right_Rotate(&T,w);
259.
260.
w = x->p->right ;
//转成case 4处理
261.
w->color = x->p->color;
262.
x->p->color = black;
263.
w->right->color = black;
264.
Left_Rotate(&T,x->p);
265.
x = T;
266.
}
267.
else
// case 4 ------------------->stop
268.
{
269.
w->color = x->p->color;
270.
x->p->color = black;
271.
w->right->color = black;
272.
Left_Rotate(&T,x->p);
273.
x = T;
274.
}
275.
}
276.
else
277.
{
278.
279.
w = x->p->left;
280.
281.
if
(w->color == red)
// case 1 ------> case 2 , case 3 ,case 4
282.
{
283.
w->color = black;
284.
x->p->color =red;
285.
Right_Rotate(&T,x->p);
286.
w = x->p->left;
287.
}
288.
if
( w->right->color == black && w->left->color == black )
//case 2 ------>go on/stop
289.
{
290.
291.
w->color = red;
292.
x = x->p;
293.
}
294.
else
if
( w->left->color == black)
// case 3 -----> case 4----->stop
295.
{
296.
w->right->color = black;
297.
w->color =red ;
298.
Left_Rotate(&T,w);
299.
300.
w = x->p->left ;
//转成case 4处理
301.
w->color = x->p->color;
302.
x->p->color = black;
303.
w->left->color = black;
304.
Right_Rotate(&T,x->p);
305.
x = T;
306.
}
307.
else
// case 4 -------------->stop
308.
{
309.
w->color = x->p->color;
310.
x->p->color = black;
311.
w->left->color = black;
312.
Right_Rotate(&T,x->p);
313.
x = T;
314.
}
315.
}
316.
}
317.
318.
x->color = black;
//可能由case2退出,那把x涂黑即可,见分析!也可能有case4退出,把根节点涂黑
319.
return
T;
320.
}
321.
Node * Interval_Delete(Node *T ,Node *z)
322.
{
323.
324.
Node * x =NULL;
325.
Node * y =z;
326.
Node * temp = y->p;
327.
enum
colors y_original_color = y->color;
//记录下删除前z的颜色
328.
if
( z->left == T_NIL)
//左子树不存在的情况
329.
{
330.
x = z->right;
331.
RB_Transplant(&T,z,z->right);
332.
333.
334.
}
335.
else
if
( z->right == T_NIL)
//右子树不存在
336.
{
337.
x = z->left;
338.
RB_Transplant(&T,z,z->left);
339.
340.
341.
}
342.
else
//左右都存在的情况
343.
{
344.
y = Tree_Minimum(z->right);
//找到后继y
345.
temp = y->p;
346.
y_original_color = y->color;
//记录下y转移前的颜色
347.
x = y->right;
348.
if
( y->p == z)
//如果y是z的子结点
349.
{
350.
x->p = y;
351.
}
352.
else
353.
{
354.
RB_Transplant(&T,y,y->right);
//如果y不是z的子结点,用y的右子树代替y的位置
355.
y->right = z->right;
356.
y->right->p = y;
357.
}
358.
RB_Transplant(&T,z,y);
//y替代z的位置 ,不论y是不是T_NIL
359.
y->left = z->left;
360.
y->left->p = y;
361.
y->color = z->color;
//把y的颜色改成z的颜色
362.
}
363.
364.
while
( temp != T_NIL )
//从要删除的结点或其后继开始向上修复红黑树
365.
{
366.
temp->Max = GetMax(temp->left->Max,temp->right->Max,temp->INT.high);
367.
temp = temp->p;
368.
}
369.
370.
371.
if
( y_original_color == black)
//判断y的颜色,若为黑色,需要修复
372.
T=Interval_Delete_Fixup(T,x);
373.
374.
return
T;
375.
}
376.
377.
Node * Tree_Search(Node *T ,
int
k)
//寻找数k是否在树中,且返回数k的地址
378.
{
379.
380.
while
(T != T_NIL && T->INT.low != k)
381.
{
382.
if
( k < T->INT.low)
383.
T=T->left;
384.
else
385.
T=T->right;
386.
}
387.
388.
if
( T == T_NIL)
389.
{
390.
return
NULL;
391.
}
392.
393.
else
394.
{
395.
return
T;
396.
}
397.
398.
}
399.
Node * Interval_Search(Node *T ,struct Interval *i)
//寻找数k是否在树中,且返回数k的地址
400.
{
401.
Node * x = T;
402.
while
(x != T_NIL && ((x->INT.high < i->low)||(x->INT.low > i->high)))
//不重叠
403.
{
404.
if
(x->left != T_NIL && x->left->Max >= i->low)
//在其左子树中搜索
405.
{
406.
x = x->left;
407.
}
408.
else
409.
{
410.
x = x->right;
411.
}
412.
}
413.
414.
return
x;
415.
}
416.
void
main()
417.
{
418.
int
A[][
2
]={
0
,
3
,
//区间
419.
5
,
8
,
420.
6
,
10
,
421.
8
,
9
,
422.
15
,
23
,
423.
16
,
21
,
424.
17
,
19
,
425.
19
,
20
,
426.
25
,
30
,
427.
26
,
26
};
428.
429.
int
length = sizeof(A)/sizeof(A[
0
]);
//数组区间的长度
430.
Node *T,*temp;
431.
struct Interval i;
432.
i.low =
22
;
433.
i.high =
25
;
434.
435.
T=Establish(A,length);
//建立红黑树,返回根节点T
436.
printf(
"中序遍历:\n"
);
437.
Inorder_Tree_Walk(T);printf(
"\n"
);
//中序遍历输出
438.
printf(
"-----------删除操作后-------------\n"
);
439.
T=Interval_Delete(T,Tree_Search(T,
6
));
440.
printf(
"中序遍历:\n"
);
441.
Inorder_Tree_Walk(T);
442.
printf(
"\n"
);
443.
444.
temp = Interval_Search(T,&i);
445.
printf(
"____%d___%d__"
, temp->INT.low,temp->INT.high);
446.
447.
}</code>