红黑树的实现(C++)
2009-05-12 22:47 Robin1986 阅读(743) 评论(0) 收藏 举报
1
// 红黑树的实现,详见《算法导论第二版》第163页。2
#ifndef RBT_H3
#define RBT_H4

5
namespace NTCI6


{7
template<typename Type>8
class RBT9

{10
public:11

enum Color
{RED, BLACK};12
class Node13

{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
else57
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
else79
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) // Case1111

{112
link->parent->color = BLACK;113
runcle->color = BLACK;114
link->parent->parent->color = RED;115
link = link->parent->parent;116
}117
else118

{119
if (link == link->parent->right) // Case2120

{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
else131

{132
Link luncle = link->parent->parent->left;133

134
if (luncle->color == RED) // Case1135

{136
link->parent->color = BLACK;137
luncle->color = BLACK;138
link->parent->parent->color = RED;139
link = link->parent->parent;140
}141
else142

{143
if (link == link->parent->left) // Case2144

{145
link = link->parent;146
RightRotate(link);147
}148
// Case3149
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
else171
removed = Successor(link);172

173
// 待删除的元素至多只有一个子结点。174
Link child;175
if (link->left != Nil())176
child = removed->left;177
else178
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
else190
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) // Case1210

{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) // Case2217

{218
rbro->color = RED;219
link = link->parent;220
}221
else222

{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
else238

{239
Link lbro = link->parent->left;240
if (lbro->color == RED) // Case1241

{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) // Case2248

{249
lbro->color = RED;250
link = link->parent;251
}252
else253

{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
else368
InsertRBT(link->left, n);369
}370
else371

{372
if (link->right == RBT::Nil())373

{374
n->parent = link;375
link->right = n;376
}377
else378
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
else390
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_H453

1
#include <iostream>2
#include <cassert>3
#include <stdexcept>4
#include "RBT.h"5

6
using namespace std;7
using namespace NTCI;8

9
int main()10


{11
try12

{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
}
浙公网安备 33010602011771号