红黑树的实现(C++)
2009-05-12 22:47 Robin1986 阅读(737) 评论(0) 编辑 收藏 举报
红黑树
1// 红黑树的实现,详见《算法导论第二版》第163页。
2#ifndef RBT_H
3#define RBT_H
4
5namespace NTCI
6{
7 template<typename Type>
8 class RBT
9 {
10 public:
11 enum Color {RED, BLACK};
12 class Node
13 {
14 public:
15 Node() : color(BLACK), left(0), right(0), parent(0) {}
16 Type item;
17 Color color;
18 Node* left;
19 Node* right;
20 Node* parent;
21 };
22 typedef Node* Link;
23
24 public:
25 RBT(Link r = Nil()) : root(r) {}
26 template<typename InputIterator>
27 RBT(InputIterator start, InputIterator end) : root(Nil())
28 {
29 for (InputIterator i = start; i != end; ++i)
30 Insert(*i);
31 }
32
33 virtual ~RBT()
34 {
35 Clear();
36 }
37
38 static Link Nil()
39 {
40 static Node nil;
41
42 return &nil;
43 }
44
45 void LeftRotate(Link link)
46 {
47 Link subr = link->right;
48 if (subr == Nil())
49 throw std::invalid_argument("待左旋的结点其右子树必须不为空");
50
51 subr->parent = link->parent;
52 if (link->parent == Nil())
53 root = subr;
54 else if (link == link->parent->left)
55 link->parent->left = subr;
56 else
57 link->parent->right = subr;
58
59 link->right = subr->left;
60 if (subr->left != Nil())
61 subr->left->parent = link;
62
63 subr->left = link;
64 link->parent = subr;
65 }
66
67 void RightRotate(Link link)
68 {
69 Link subl = link->left;
70 if (subl == Nil())
71 throw std::invalid_argument("待右旋的结点其左子树必须不为空");
72
73 subl->parent = link->parent;
74 if (link->parent == Nil())
75 root = subl;
76 else if (link == link->parent->left)
77 link->parent->left = subl;
78 else
79 link->parent->right = subl;
80
81 link->left = subl->right;
82 if (subl->right != Nil())
83 subl->right->parent = link;
84
85 subl->right = link;
86 link->parent = subl;
87 }
88
89 void Insert(Type item)
90 {
91 Link n = new Node();
92 n->item = item;
93 n->color = RED;
94 n->left = Nil();
95 n->right = Nil();
96 n->parent = Nil();
97
98 InsertRBT(root, n);
99 RBInsertFixup(n);
100 }
101
102 void RBInsertFixup(Link link)
103 {
104 while (link->parent->color == RED)
105 {
106 if (link->parent == link->parent->parent->left)
107 {
108 Link runcle = link->parent->parent->right;
109
110 if (runcle->color == RED) // Case1
111 {
112 link->parent->color = BLACK;
113 runcle->color = BLACK;
114 link->parent->parent->color = RED;
115 link = link->parent->parent;
116 }
117 else
118 {
119 if (link == link->parent->right) // Case2
120 {
121 link = link->parent;
122 LeftRotate(link);
123 }
124
125 link->parent->color = BLACK;
126 link->parent->parent->color = RED;
127 RightRotate(link->parent->parent);
128 }
129 }
130 else
131 {
132 Link luncle = link->parent->parent->left;
133
134 if (luncle->color == RED) // Case1
135 {
136 link->parent->color = BLACK;
137 luncle->color = BLACK;
138 link->parent->parent->color = RED;
139 link = link->parent->parent;
140 }
141 else
142 {
143 if (link == link->parent->left) // Case2
144 {
145 link = link->parent;
146 RightRotate(link);
147 }
148 // Case3
149 link->parent->color = BLACK;
150 link->parent->parent->color = RED;
151 LeftRotate(link->parent->parent);
152 }
153 }
154 }
155
156 root->color = BLACK;
157 }
158
159 Link Remove(Link link)
160 {
161 // 删除空节点时抛出参数无效的异常。
162 if (link == Nil())
163 throw std::invalid_argument("待删除的结点为空");
164
165 // 先确定将要被删除的结点。如果结点只有一个或零个子结点,则原元素将被删除,
166 // 否侧其后继结点将被删除。
167 Link removed;
168 if (link->left == Nil() || link->right == Nil())
169 removed = link;
170 else
171 removed = Successor(link);
172
173 // 待删除的元素至多只有一个子结点。
174 Link child;
175 if (link->left != Nil())
176 child = removed->left;
177 else
178 child = removed->right;
179
180 // 先设置子结点的新的父节点。
181 child->parent = removed->parent;
182
183 // 如果待删除的结点为根节点,直接将根结点设置为子结点,
184 if (removed->parent == Nil())
185 root = child;
186 // 否则将待删除结点的父节点的子结点指向待删除结点的子结点。
187 else if (removed == removed->parent->left)
188 removed->parent->left = child;
189 else
190 removed->parent->right = child;
191
192 // 如果原结点和被删除的结点不同,则说明原结点具有两个子结点,此时需要将
193 // 被删除结点的值复制到原结点。
194 if (link != removed)
195 link->item = removed->item;
196
197 if (removed->color == BLACK)
198 RBRemoveFixup(child);
199 return removed;
200 }
201
202 void RBRemoveFixup(Link link)
203 {
204 while (link != root && link->color == BLACK)
205 {
206 if (link == link->parent->left)
207 {
208 Link rbro = link->parent->right;
209 if (rbro->color == RED) // Case1
210 {
211 rbro->color = BLACK;
212 link->parent->color = RED;
213 LeftRotate(link->parent);
214 rbro = link->parent->right;
215 }
216 if (rbro->left->color == BLACK && rbro->right->color == BLACK) // Case2
217 {
218 rbro->color = RED;
219 link = link->parent;
220 }
221 else
222 {
223 if (rbro->right->color == BLACK)
224 {
225 rbro->left->color = BLACK;
226 rbro->color = RED;
227 RightRotate(rbro);
228 rbro = link->parent->right;
229 }
230 rbro->color = link->parent->color;
231 link->parent->color = BLACK;
232 rbro->right->color = BLACK;
233 LeftRotate(link->parent);
234 link = root;
235 }
236 }
237 else
238 {
239 Link lbro = link->parent->left;
240 if (lbro->color == RED) // Case1
241 {
242 lbro->color = BLACK;
243 link->parent->color = RED;
244 RightRotate(link->parent);
245 lbro = link->parent->left;
246 }
247 if (lbro->right->color == BLACK && lbro->left->color == BLACK) // Case2
248 {
249 lbro->color = RED;
250 link = link->parent;
251 }
252 else
253 {
254 if (lbro->left->color == BLACK)
255 {
256 lbro->right->color = BLACK;
257 lbro->color = RED;
258 LeftRotate(lbro);
259 lbro = link->parent->left;
260 }
261 lbro->color = link->parent->color;
262 link->parent->color = BLACK;
263 lbro->left->color = BLACK;
264 RightRotate(link->parent);
265 link = root;
266 }
267 }
268 }
269 link->color = BLACK;
270 }
271
272 Link Remove(Type item)
273 {
274 Link link = Search(item);
275 return Remove(link);
276 }
277
278 Link Search(Type item)
279 {
280 return SearchRBT(root, item);
281 }
282
283 int Maximum()
284 {
285 Link max = MaximumRBT(root);
286 if (max == 0)
287 throw std::out_of_range("红黑树为空");
288 return max->item;
289 }
290
291 int Minimun()
292 {
293 Link min = MinimunRBT(root);
294 if (min == 0)
295 throw std::out_of_range("红黑树为空");
296 return min->item;
297 }
298
299 void InorderWalk(std::ostream& out)
300 {
301 InorderWalkRBT(root, out);
302 }
303
304 Link Successor(Link link)
305 {
306 // 如果右子结点不为空,则返回右子树的最小结点,
307 if (link->right != Nil())
308 return MinimunRBT(link->right);
309
310 // 否则后继元素是一个祖先结点,该结点的左子结点也是祖先结点。
311 Link p = link->parent;
312 while (p != Nil() && link == p->right)
313 {
314 link = p;
315 p = link->parent;
316 }
317
318 return p;
319 }
320
321 Link Predecessor(Link link)
322 {
323 if (link->left != Nil())
324 return MaximumRBT(link->left);
325
326 Link p = link->parent;
327 while (p != Nil() && link == p->left)
328 {
329 link = p;
330 p = link->parent;
331 }
332
333 return p;
334 }
335
336 int Heigth()
337 {
338 return HeightRBT(root);
339 }
340
341 int Length()
342 {
343 return LengthRBT(root);
344 }
345
346 void Clear()
347 {
348 ClearRBT(root);
349 }
350
351 private:
352 void InsertRBT(Link& link, Link n)
353 {
354 if (link == RBT::Nil())
355 {
356 link = n;
357 return;
358 }
359
360 if (n->item < link->item)
361 {
362 if (link->left == RBT::Nil())
363 {
364 n->parent = link;
365 link ->left = n;
366 }
367 else
368 InsertRBT(link->left, n);
369 }
370 else
371 {
372 if (link->right == RBT::Nil())
373 {
374 n->parent = link;
375 link->right = n;
376 }
377 else
378 InsertRBT(link->right, n);
379 }
380
381 }
382
383 Link SearchRBT(Link link, Type item)
384 {
385 if (link == Nil() || link->item == item)
386 return link;
387 if (link->item > item)
388 return SearchRBT(link->left, item);
389 else
390 return SearchRBT(link->right, item);
391 }
392
393 void InorderWalkRBT(Link link, std::ostream& out)
394 {
395 if (link == Nil())
396 return;
397
398 InorderWalkRBT(link->left, out);
399 out << link->item << " ";
400 InorderWalkRBT(link->right, out);
401 }
402
403 Link MaximumRBT(Link link)
404 {
405 while (link->right != Nil())
406 link = link->right;
407 return link;
408 }
409
410 Link MinimunRBT(Link link)
411 {
412 while (link->left != Nil())
413 link = link->left;
414 return link;
415 }
416
417 int HeightRBT(Link link)
418 {
419 if (link == Nil())
420 return 0;
421
422 int lh, rh;
423 lh = HeightRBT(link->left);
424 rh = HeightRBT(link->right);
425 return std::max(lh, rh) + 1;
426 }
427
428
429 int LengthRBT(Link link)
430 {
431 if (link == Nil())
432 return 0;
433 return LengthRBT(link->left) + LengthRBT(link->right) + 1;
434 }
435
436 void ClearRBT(Link& link)
437 {
438 if (link == Nil())
439 return;
440 ClearRBT(link->left);
441 ClearRBT(link->right);
442 delete link;
443
444 link = Nil();
445 }
446
447 private:
448 Link root;
449 };
450}
451
452#endif // RBT_H
453
1// 红黑树的实现,详见《算法导论第二版》第163页。
2#ifndef RBT_H
3#define RBT_H
4
5namespace NTCI
6{
7 template<typename Type>
8 class RBT
9 {
10 public:
11 enum Color {RED, BLACK};
12 class Node
13 {
14 public:
15 Node() : color(BLACK), left(0), right(0), parent(0) {}
16 Type item;
17 Color color;
18 Node* left;
19 Node* right;
20 Node* parent;
21 };
22 typedef Node* Link;
23
24 public:
25 RBT(Link r = Nil()) : root(r) {}
26 template<typename InputIterator>
27 RBT(InputIterator start, InputIterator end) : root(Nil())
28 {
29 for (InputIterator i = start; i != end; ++i)
30 Insert(*i);
31 }
32
33 virtual ~RBT()
34 {
35 Clear();
36 }
37
38 static Link Nil()
39 {
40 static Node nil;
41
42 return &nil;
43 }
44
45 void LeftRotate(Link link)
46 {
47 Link subr = link->right;
48 if (subr == Nil())
49 throw std::invalid_argument("待左旋的结点其右子树必须不为空");
50
51 subr->parent = link->parent;
52 if (link->parent == Nil())
53 root = subr;
54 else if (link == link->parent->left)
55 link->parent->left = subr;
56 else
57 link->parent->right = subr;
58
59 link->right = subr->left;
60 if (subr->left != Nil())
61 subr->left->parent = link;
62
63 subr->left = link;
64 link->parent = subr;
65 }
66
67 void RightRotate(Link link)
68 {
69 Link subl = link->left;
70 if (subl == Nil())
71 throw std::invalid_argument("待右旋的结点其左子树必须不为空");
72
73 subl->parent = link->parent;
74 if (link->parent == Nil())
75 root = subl;
76 else if (link == link->parent->left)
77 link->parent->left = subl;
78 else
79 link->parent->right = subl;
80
81 link->left = subl->right;
82 if (subl->right != Nil())
83 subl->right->parent = link;
84
85 subl->right = link;
86 link->parent = subl;
87 }
88
89 void Insert(Type item)
90 {
91 Link n = new Node();
92 n->item = item;
93 n->color = RED;
94 n->left = Nil();
95 n->right = Nil();
96 n->parent = Nil();
97
98 InsertRBT(root, n);
99 RBInsertFixup(n);
100 }
101
102 void RBInsertFixup(Link link)
103 {
104 while (link->parent->color == RED)
105 {
106 if (link->parent == link->parent->parent->left)
107 {
108 Link runcle = link->parent->parent->right;
109
110 if (runcle->color == RED) // Case1
111 {
112 link->parent->color = BLACK;
113 runcle->color = BLACK;
114 link->parent->parent->color = RED;
115 link = link->parent->parent;
116 }
117 else
118 {
119 if (link == link->parent->right) // Case2
120 {
121 link = link->parent;
122 LeftRotate(link);
123 }
124
125 link->parent->color = BLACK;
126 link->parent->parent->color = RED;
127 RightRotate(link->parent->parent);
128 }
129 }
130 else
131 {
132 Link luncle = link->parent->parent->left;
133
134 if (luncle->color == RED) // Case1
135 {
136 link->parent->color = BLACK;
137 luncle->color = BLACK;
138 link->parent->parent->color = RED;
139 link = link->parent->parent;
140 }
141 else
142 {
143 if (link == link->parent->left) // Case2
144 {
145 link = link->parent;
146 RightRotate(link);
147 }
148 // Case3
149 link->parent->color = BLACK;
150 link->parent->parent->color = RED;
151 LeftRotate(link->parent->parent);
152 }
153 }
154 }
155
156 root->color = BLACK;
157 }
158
159 Link Remove(Link link)
160 {
161 // 删除空节点时抛出参数无效的异常。
162 if (link == Nil())
163 throw std::invalid_argument("待删除的结点为空");
164
165 // 先确定将要被删除的结点。如果结点只有一个或零个子结点,则原元素将被删除,
166 // 否侧其后继结点将被删除。
167 Link removed;
168 if (link->left == Nil() || link->right == Nil())
169 removed = link;
170 else
171 removed = Successor(link);
172
173 // 待删除的元素至多只有一个子结点。
174 Link child;
175 if (link->left != Nil())
176 child = removed->left;
177 else
178 child = removed->right;
179
180 // 先设置子结点的新的父节点。
181 child->parent = removed->parent;
182
183 // 如果待删除的结点为根节点,直接将根结点设置为子结点,
184 if (removed->parent == Nil())
185 root = child;
186 // 否则将待删除结点的父节点的子结点指向待删除结点的子结点。
187 else if (removed == removed->parent->left)
188 removed->parent->left = child;
189 else
190 removed->parent->right = child;
191
192 // 如果原结点和被删除的结点不同,则说明原结点具有两个子结点,此时需要将
193 // 被删除结点的值复制到原结点。
194 if (link != removed)
195 link->item = removed->item;
196
197 if (removed->color == BLACK)
198 RBRemoveFixup(child);
199 return removed;
200 }
201
202 void RBRemoveFixup(Link link)
203 {
204 while (link != root && link->color == BLACK)
205 {
206 if (link == link->parent->left)
207 {
208 Link rbro = link->parent->right;
209 if (rbro->color == RED) // Case1
210 {
211 rbro->color = BLACK;
212 link->parent->color = RED;
213 LeftRotate(link->parent);
214 rbro = link->parent->right;
215 }
216 if (rbro->left->color == BLACK && rbro->right->color == BLACK) // Case2
217 {
218 rbro->color = RED;
219 link = link->parent;
220 }
221 else
222 {
223 if (rbro->right->color == BLACK)
224 {
225 rbro->left->color = BLACK;
226 rbro->color = RED;
227 RightRotate(rbro);
228 rbro = link->parent->right;
229 }
230 rbro->color = link->parent->color;
231 link->parent->color = BLACK;
232 rbro->right->color = BLACK;
233 LeftRotate(link->parent);
234 link = root;
235 }
236 }
237 else
238 {
239 Link lbro = link->parent->left;
240 if (lbro->color == RED) // Case1
241 {
242 lbro->color = BLACK;
243 link->parent->color = RED;
244 RightRotate(link->parent);
245 lbro = link->parent->left;
246 }
247 if (lbro->right->color == BLACK && lbro->left->color == BLACK) // Case2
248 {
249 lbro->color = RED;
250 link = link->parent;
251 }
252 else
253 {
254 if (lbro->left->color == BLACK)
255 {
256 lbro->right->color = BLACK;
257 lbro->color = RED;
258 LeftRotate(lbro);
259 lbro = link->parent->left;
260 }
261 lbro->color = link->parent->color;
262 link->parent->color = BLACK;
263 lbro->left->color = BLACK;
264 RightRotate(link->parent);
265 link = root;
266 }
267 }
268 }
269 link->color = BLACK;
270 }
271
272 Link Remove(Type item)
273 {
274 Link link = Search(item);
275 return Remove(link);
276 }
277
278 Link Search(Type item)
279 {
280 return SearchRBT(root, item);
281 }
282
283 int Maximum()
284 {
285 Link max = MaximumRBT(root);
286 if (max == 0)
287 throw std::out_of_range("红黑树为空");
288 return max->item;
289 }
290
291 int Minimun()
292 {
293 Link min = MinimunRBT(root);
294 if (min == 0)
295 throw std::out_of_range("红黑树为空");
296 return min->item;
297 }
298
299 void InorderWalk(std::ostream& out)
300 {
301 InorderWalkRBT(root, out);
302 }
303
304 Link Successor(Link link)
305 {
306 // 如果右子结点不为空,则返回右子树的最小结点,
307 if (link->right != Nil())
308 return MinimunRBT(link->right);
309
310 // 否则后继元素是一个祖先结点,该结点的左子结点也是祖先结点。
311 Link p = link->parent;
312 while (p != Nil() && link == p->right)
313 {
314 link = p;
315 p = link->parent;
316 }
317
318 return p;
319 }
320
321 Link Predecessor(Link link)
322 {
323 if (link->left != Nil())
324 return MaximumRBT(link->left);
325
326 Link p = link->parent;
327 while (p != Nil() && link == p->left)
328 {
329 link = p;
330 p = link->parent;
331 }
332
333 return p;
334 }
335
336 int Heigth()
337 {
338 return HeightRBT(root);
339 }
340
341 int Length()
342 {
343 return LengthRBT(root);
344 }
345
346 void Clear()
347 {
348 ClearRBT(root);
349 }
350
351 private:
352 void InsertRBT(Link& link, Link n)
353 {
354 if (link == RBT::Nil())
355 {
356 link = n;
357 return;
358 }
359
360 if (n->item < link->item)
361 {
362 if (link->left == RBT::Nil())
363 {
364 n->parent = link;
365 link ->left = n;
366 }
367 else
368 InsertRBT(link->left, n);
369 }
370 else
371 {
372 if (link->right == RBT::Nil())
373 {
374 n->parent = link;
375 link->right = n;
376 }
377 else
378 InsertRBT(link->right, n);
379 }
380
381 }
382
383 Link SearchRBT(Link link, Type item)
384 {
385 if (link == Nil() || link->item == item)
386 return link;
387 if (link->item > item)
388 return SearchRBT(link->left, item);
389 else
390 return SearchRBT(link->right, item);
391 }
392
393 void InorderWalkRBT(Link link, std::ostream& out)
394 {
395 if (link == Nil())
396 return;
397
398 InorderWalkRBT(link->left, out);
399 out << link->item << " ";
400 InorderWalkRBT(link->right, out);
401 }
402
403 Link MaximumRBT(Link link)
404 {
405 while (link->right != Nil())
406 link = link->right;
407 return link;
408 }
409
410 Link MinimunRBT(Link link)
411 {
412 while (link->left != Nil())
413 link = link->left;
414 return link;
415 }
416
417 int HeightRBT(Link link)
418 {
419 if (link == Nil())
420 return 0;
421
422 int lh, rh;
423 lh = HeightRBT(link->left);
424 rh = HeightRBT(link->right);
425 return std::max(lh, rh) + 1;
426 }
427
428
429 int LengthRBT(Link link)
430 {
431 if (link == Nil())
432 return 0;
433 return LengthRBT(link->left) + LengthRBT(link->right) + 1;
434 }
435
436 void ClearRBT(Link& link)
437 {
438 if (link == Nil())
439 return;
440 ClearRBT(link->left);
441 ClearRBT(link->right);
442 delete link;
443
444 link = Nil();
445 }
446
447 private:
448 Link root;
449 };
450}
451
452#endif // RBT_H
453
测试代码
1#include <iostream>
2#include <cassert>
3#include <stdexcept>
4#include "RBT.h"
5
6using namespace std;
7using namespace NTCI;
8
9int main()
10{
11 try
12 {
13 int array[] = {5, 4, 7, 2, 6, 8, 9, 20, 12, 16, 11, 14};
14 RBT<int> rbt(array, array + 12);
15
16 cout << "排序后:";
17 rbt.InorderWalk(cout);
18 cout << endl;
19
20 RBT<int>::Link link = rbt.Search(5);
21 assert(rbt.Successor(link)->item == 6);
22 assert(rbt.Predecessor(link)->item == 4);
23 cout << "红黑树高度:" << rbt.Heigth() << endl;
24 cout << "最大值:" << rbt.Maximum() << endl;
25 cout << "最小值:" << rbt.Minimun() << endl;
26
27 rbt.Remove(9);
28
29 link = rbt.Search(7);
30 assert(link->item == 7);
31
32 link = rbt.Remove(link);
33 delete link;
34 assert(rbt.Length() == 10);
35 cout << "删除元素7后:";
36 rbt.InorderWalk(cout);
37 cout << endl;
38
39 rbt.Clear();
40 assert(rbt.Length() == 0);
41
42 }
43 catch (exception& e)
44 {
45 cout << "发生异常:" << e.what() << endl;
46 }
47 return 0;
48}
1#include <iostream>
2#include <cassert>
3#include <stdexcept>
4#include "RBT.h"
5
6using namespace std;
7using namespace NTCI;
8
9int main()
10{
11 try
12 {
13 int array[] = {5, 4, 7, 2, 6, 8, 9, 20, 12, 16, 11, 14};
14 RBT<int> rbt(array, array + 12);
15
16 cout << "排序后:";
17 rbt.InorderWalk(cout);
18 cout << endl;
19
20 RBT<int>::Link link = rbt.Search(5);
21 assert(rbt.Successor(link)->item == 6);
22 assert(rbt.Predecessor(link)->item == 4);
23 cout << "红黑树高度:" << rbt.Heigth() << endl;
24 cout << "最大值:" << rbt.Maximum() << endl;
25 cout << "最小值:" << rbt.Minimun() << endl;
26
27 rbt.Remove(9);
28
29 link = rbt.Search(7);
30 assert(link->item == 7);
31
32 link = rbt.Remove(link);
33 delete link;
34 assert(rbt.Length() == 10);
35 cout << "删除元素7后:";
36 rbt.InorderWalk(cout);
37 cout << endl;
38
39 rbt.Clear();
40 assert(rbt.Length() == 0);
41
42 }
43 catch (exception& e)
44 {
45 cout << "发生异常:" << e.what() << endl;
46 }
47 return 0;
48}