算法11---红黑树不带父结点指针的插入实现
1 #include <iostream>
2 using namespace std;
3 #define BLACK 0
4 #define RED 1
5 #define Nil -1
6 #define LEN sizeof(struct Tree)
7 struct Tree
8 {
9 struct Tree*left;
10 struct Tree*right;
11 int key;
12 int color;
13 };
14 struct Tree*root=NULL;
15 struct Tree*nil=NULL;
16 //非递归版本的二叉查找树查找函数
17 struct Tree*ITERATIVE_TREE_SEARCH(struct Tree*x,int k,struct Tree*&p1,struct Tree*&p2)
18 {//
19 while (x!=nil&&k!=x->key)
20 {
21 p1=x;
22 if (k<x->key)
23 {
24 x=x->left;
25 }
26 else x=x->right;
27 if(k!=x->key)//如果没找到了待查找值,那么继续记录其祖父和父结点值。
28 {
29 p2=p1;
30 p1=x;
31 }
32 }
33 return x;
34 }
35 void LEFT_ROTATE(struct Tree*T,struct Tree*x)
36 {//左旋转:分三个步骤①②③来叙述旋转代码的。
37 struct Tree*p1=nil,*p2=nil;
38 struct Tree*y=x->right;//设置y结点。
39 x->right=y->left;//本行代码以及下面的if结构表达的是“y的左孩子成为x的右孩子”。①
40 ITERATIVE_TREE_SEARCH(root,x->key,p1,p2);
41 if(p1==nil)//本行代码以及下面的if-else结构表达的过程是“y成为该子树新的根”。②
42 {
43 root=y;
44 }
45 else if(x==p1->left)
46 {
47 p1->left=y;
48 }
49 else p1->right=y;
50 y->left=x;//本行代码以及下面一行都表达了“x成为y的左孩子”。③
51 }
52 void RIGHT_ROTATE(struct Tree*T,struct Tree*x)
53 {//右旋转
54 struct Tree*p1=nil,*p2=nil;
55 struct Tree*y=x->left;
56 x->left=y->right;
57 ITERATIVE_TREE_SEARCH(root,x->key,p1,p2);
58 if(p1==nil)
59 {
60 root=y;
61 }
62 else if(x==p1->right)
63 {
64 p1->right=y;
65 }
66 else p1->left=y;
67 y->right=x;
68 }
69 void RB_INSERT_INSERT_FIXUP(struct Tree*T,struct Tree*z)
70 {
71 struct Tree*p1=nil,*p2=nil;
72 ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1=z->parent,p2=z->parent->parent
73 while (1)
74 {
75 ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1是父结点 p2是祖父结点
76 if (p1->color!=RED)
77 {
78 break;
79 }
80 if (p1==p2->left)
81 {
82 struct Tree*y=p2->right;//叔结点
83 if (y->color==RED)//情况一:叔结点为红色
84 {//给p1,y,p2着色以保持性质5。并且解决了z的父结点和z都是红色结点问题
85 p1->color=BLACK;
86 y->color=BLACK;
87 p2->color=RED;
88 z=p2;//把z的祖父结点当成新结点z进入下一次循环
89 }
90 else
91 {
92 if (z==p1->right)//情况二:检查z是否是一个右孩子且叔结点为黑色,前提是p1结点不是叶子结点
93 {//使用一个左旋让情况2转变为情况3
94 z=p1;
95 LEFT_ROTATE(T,z);//由于进入if语句后可知旋转结点不可能是叶子结点,这样就不用判断z是否是叶子结点了。
96 ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1=z->parent,p2=z->parent->parent
97 }
98 p1->color=BLACK;//情况三:是z是一个左孩子且叔结点为黑色,改变z的父和祖父结点颜色并做一次右旋,以保持性质5。
99 p2->color=RED;
100 if(p2!=nil) RIGHT_ROTATE(T,p2);//由于p2可能是叶子结点,所以最好还是用一个if判断
101 }
102 }
103 else//下面else分支类似于上面
104 {
105 struct Tree*y=p2->left;
106 if (y->color==RED)
107 {
108 p1->color=BLACK;
109 y->color=BLACK;
110 p2->color=RED;
111 z=p2;
112 }
113 else
114 {
115 if (z==p1->left)
116 {
117 z=p1;
118 RIGHT_ROTATE(T,z);
119 ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);
120 }
121 p1->color=BLACK;
122 p2->color=RED;
123 if(p2!=nil) LEFT_ROTATE(T,p2);
124 }
125 }
126 }
127 root->color=BLACK;//最后给根结点着为黑色。
128 }
129 void RB_INSERT(struct Tree*T,struct Tree*z)
130 {
131 struct Tree*y=nil;
132 struct Tree*x=root;
133 while (x!=nil)
134 {
135 y=x;
136 if (z->key<x->key)
137 {
138 x=x->left;
139 }
140 else x=x->right;
141 }
142 if (y==nil)
143 {
144 root=z;
145 }
146 else if(z->key<y->key)
147 {
148 y->left=z;
149 }
150 else y->right=z;
151 z->left=nil;
152 z->right=nil;
153 z->color=RED;
154 RB_INSERT_INSERT_FIXUP(T,z);
155 }
156 //中序遍历
157 void InOderTraverse(struct Tree *p)
158 {
159 if (p!=nil)
160 {
161 InOderTraverse(p->left);
162 cout<<p->key<<" "<<p->color<<" "<<endl;
163 InOderTraverse(p->right);
164 }
165 }
166 void main()
167 {
168 nil=new struct Tree[LEN];
169 nil->key=Nil;nil->color=BLACK;
170 root=nil;
171 int i=0;
172 struct Tree*ROOT=new struct Tree[LEN];
173 cin>>ROOT->key;
174 RB_INSERT(nil,ROOT);
175 root=ROOT;
176 while (i!=12)
177 {
178 struct Tree*z=new struct Tree[LEN];
179 cin>>z->key;
180 RB_INSERT(root,z);
181 i++;
182 }
183 InOderTraverse(root);
184 }