ZZU第四届程序设计大赛 5-红黑树
http://acm.nyist.net/JudgeOnline/problem.php?pid=202
5.红黑树
什么是红黑树呢,顾名思义,跟枣树类似,红黑树是一种叶子是黑色果子是红色的树。。。。
当然,这个是我说的.......
《算法导论》上可不是这么说的:
如果一个二叉查找树满足下面的红黑性质,那么则为一个红黑树。
1)每个节点或是红的,或者是黑的。
2)每个叶子节点(NIL)是黑色的
3)如果一个节点是红色的,那么他的两个儿子都是黑的。
4)根节点是黑色的。
5)对于每个节点,从该节点到子孙节点的所有路径上包含相同数目的黑色节点。
我们在整个过程中会用到这些性质,当然,为了公平起见,其实即使你不知道这些性质,
这个题目也是可以完成的( 为什么不早说。。。。。)。在红黑树的各种操作中,其核心操作
被称为旋转,那么什么是旋转呢?我们来看一个例子:
假设我们这里截取红黑树的一部分,放在左边,通过操作如果可以把他转化为右边的形
式,那么我们就称将根为x 的子树其进行了左旋,反之我们称将根为Y 的树进行右旋:
恰好慢板同学把自己红黑树弄乱了,然后请你帮忙进行修复,他将向你描述他的红黑树
( 混乱的。。。)。然后告诉你他需要用哪种方式旋转某个节点。在你完成工作之后,直接
向大黄提交新的树的中序遍历结果就好了。
Input
输入分两部分:
第一部分:一个整数T(1<=T<=10)表示测试的组数。
10
第二部分:
第一行是一个数字N,表示红黑树的节点个数。n < 0 < 10
然后下面有N 行,每行三个数字,每个数字的大小都在-1 ~ n - 1 之间。第一个数字表示
当前节点的标号,后面两个数字表示这个节点的左孩子和右孩子。如果是-1 的话表示是空
节点。对于所有的输入来说标号为0 节点为根。
然后是一个数字M 表示需要旋转的次数。M < 100
接下来M 行有两个数字,分别表示你要旋转的节点标号和你需要的操作。标号的范围
为0~n-1 , 如果标号后面的数字1,那么表示为左旋。如果为1,则是右旋。
Output
每组测试返回N 行数字,表示对于树的中序遍历。在每组测试数据之后留一行空行。
Sample
input1
3
0 1 2
1 -1 -1
2 -1 -1
1
0 1
output
1
0
2
做这个题时正在学平衡二叉树,刚学了一堆神马旋转的,以为很随意,结果到最后把自己给旋晕了~~~实在不行了看学姐的代码,看到一句:旋转不影响红黑树中序遍历~各种无语。。。。。。知道这条性质,这题只不过是建立二叉树,中序遍历即可~数组开大点,要不runtime error~~
1 //106481 jiaolinfeng 红黑树 Accepted 4 228 C/C++ 12-18 09:11:28
2 //105094 jiaolinfeng 红黑树 WrongAnswer -- -- C/C++ 12-12 22:18:22
3 //105090 jiaolinfeng 红黑树 WrongAnswer -- -- C/C++ 12-12 22:10:34
4 #include<stdio.h>
5 #include<string.h>
6 int t[200][2];
7 int nn;
8 void InorderTravel(int x)
9 {
10 if(x == -1)
11 return;
12 if(x > nn)
13 return;
14 else
15 {
16 InorderTravel(t[x][0]);
17 printf("%d\n", x);
18 InorderTravel(t[x][1]);
19 }
20 }
21 int main()
22 {
23 int tcases, i, x, y, z;
24 scanf("%d", &tcases);
25 while(tcases--)
26 {
27 scanf("%d", &nn);
28 memset(t, 0, sizeof(t));
29 for(i = 0; i < nn; i++)
30 {
31 scanf("%d%d%d", &x, &y, &z);
32 t[x][0] = y;
33 t[x][1] = z;
34 }
35 scanf("%d", &x);
36 for(i = 0; i < x; i++)
37 scanf("%d%d", &y, &z);
38 InorderTravel(0);
39 putchar(10);
40 }
41 return 0;
42 }