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