二叉查找树(BST)的实现(C++)
2009-05-06 21:35 Robin1986 阅读(1865) 评论(1) 收藏 举报1
//二叉搜索树的实现,其原理参见《算法导论第二版》第151页。2

3
#ifndef BST_H4
#define BST_H5

6
#include <iostream>7
#include <stdexcept>8

9
namespace NTCI10


{11
template<typename Type>12
class BST13

{14
public:15
struct Node16

{17
Type item;18
Node* left;19
Node* right;20
Node* parent;21
};22
typedef Node* Link;23

24
public:25

BST(Link r = 0) : root(r)
{}26
template<typename InputIterator>27
BST(InputIterator start, InputIterator end) : root(0)28

{29
for (InputIterator i = start; i != end; ++i)30
Insert(*i);31
}32

33
virtual ~BST()34

{35
Clear();36
}37
void Insert(Type item)38

{39
Link n = new Node();40
n->item = item;41
InsertBST(root, n);42
}43

44
Link Remove(Link link)45

{46
// 删除空节点时抛出参数无效的异常。47
if (link == 0)48
throw std::invalid_argument("待删除的结点为空");49

50
// 先确定将要被删除的结点。如果结点只有一个或零个子结点,则原元素将被删除,51
// 否侧其后继结点将被删除。52
Link removed;53
if (link->left == 0 || link->right == 0)54
removed = link;55
else56
removed = Successor(link);57

58
// 待删除的元素至多只有一个子结点。59
Link child = 0;60
if (link->left != 0)61
child = removed->left;62
else63
child = removed->right;64

65
// 先设置子结点的新的父节点。66
if (child != 0)67
child->parent = removed->parent;68

69
// 如果待删除的结点为根节点,直接将根结点设置为子结点,70
if (removed->parent == 0)71
root = child;72
// 否则将待删除结点的父节点的子结点指向待删除结点的子结点。73
else if (removed == removed->parent->left)74
removed->parent->left = child;75
else76
removed->parent->right = child;77

78
// 如果原结点和被删除的结点不同,则说明原结点具有两个子结点,此时需要将79
// 被删除结点的值复制到原结点。80
if (link != removed)81
link->item = removed->item;82

83
return removed;84
}85

86
Link Remove(Type item)87

{88
Link link = Search(item);89
return Remove(link);90
}91

92
Link Search(Type item)93

{94
return SearchBST(root, item);95
}96

97
int Maximum()98

{99
Link max = MaximumBST(root);100
if (max == 0)101
throw std::out_of_range("二叉搜索树为空");102
return max->item;103
}104

105
int Minimun()106

{107
Link min = MinimunBST(root);108
if (min == 0)109
throw std::out_of_range("二叉搜索树为空");110
return min->item;111
}112

113
void InorderWalk(std::ostream& out)114

{115
InorderWalkBST(root, out);116
}117

118
Link Successor(Link link)119

{120
// 如果右子结点不为空,则返回右子树的最小结点,121
if (link->right != 0)122
return MinimunBST(link->right);123

124
// 否则后继元素是一个祖先结点,该结点的左子结点也是祖先结点。125
Link p = link->parent;126
while (p != 0 && link == p->right)127

{128
link = p;129
p = link->parent;130
}131

132
return p;133
}134

135
Link Predecessor(Link link)136

{137
if (link->left != 0)138
return MaximumBST(link->left);139

140
Link p = link->parent;141
while (p != 0 && link == p->left)142

{143
link = p;144
p = link->parent;145
}146

147
return p;148
}149

150
int Heigth()151

{152
return HeightBST(root);153
}154

155
int Length()156

{157
return LengthBST(root);158
}159

160
void Clear()161

{162
ClearBST(root);163
}164

165
void InsertBST(Link& root, Link n)166

{167
if (root == 0)168

{169
root = n;170
return;171
}172

173
if (n->item < root->item)174

{175
if (root->left == 0)176

{177
n->parent = root;178
root ->left = n;179
}180
else181
InsertBST(root->left, n);182
}183
else184

{185
if (root->right == 0)186

{187
n->parent = root;188
root->right = n;189
}190
else191
InsertBST(root->right, n);192
}193

194
}195
private:196
Link SearchBST(Link root, Type item)197

{198
if (root == 0 || root->item == item)199
return root;200
if (root->item > item)201
return SearchBST(root->left, item);202
else203
return SearchBST(root->right, item);204
}205

206
void InorderWalkBST(Link root, std::ostream& out)207

{208
if (root == 0)209
return;210

211
InorderWalkBST(root->left, out);212
out << root->item << " ";213
InorderWalkBST(root->right, out);214
}215

216
Link MaximumBST(Link link)217

{218
while (link->right != 0)219
link = link->right;220
return link;221
}222

223
Link MinimunBST(Link link)224

{225
while (link->left != 0)226
link = link->left;227
return link;228
}229

230
int HeightBST(Link root)231

{232
if (root == 0)233
return 0;234

235
int lh, rh;236
lh = HeightBST(root->left);237
rh = HeightBST(root->right);238
return std::max(lh, rh) + 1;239
}240

241

242
int LengthBST(Link root)243

{244
if (root == 0)245
return 0;246
return LengthBST(root->left) + LengthBST(root->right) + 1;247
}248

249
void ClearBST(Link& root)250

{251
if (root == 0)252
return;253
ClearBST(root->left);254
ClearBST(root->right);255
delete root;256

257
root = 0;258
}259

260
private:261
Link root;262
};263
}264

265
#endif // BST_H266

1
#include <iostream>2
#include <cassert>3
#include <stdexcept>4
#include "BST.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};14
BST<int> bst(array, array + 6);15

16
cout << "排序后:";17
bst.InorderWalk(cout);18
cout << endl;19

20
BST<int>::Link link = bst.Search(5);21
assert(bst.Successor(link)->item == 6);22
assert(bst.Predecessor(link)->item == 4);23
cout << "二叉树高度:" << bst.Heigth() << endl;24
cout << "最大值:" << bst.Maximum() << endl;25
cout << "最小值:" << bst.Minimun() << endl;26

27
bst.Remove(9);28

29
link = bst.Search(7);30
assert(link->item == 7);31

32
link = bst.Remove(link);33
delete link;34
assert(bst.Length() == 5);35
cout << "删除元素7后:";36
bst.InorderWalk(cout);37
cout << endl;38

39
bst.Clear();40
assert(bst.Length() == 0);41
}42
catch (exception& e)43

{44
cout << "发生异常:" << e.what() << endl;45
}46

47
return 0;48
}49

要实现随机构造的二叉查找树很容易,先调用标准库的random_shuffle函数对数组进行随机重排,然后再构造二叉搜索树就OK了~
欢迎大家就程序正确性以及代码风格等方面提出建议~
浙公网安备 33010602011771号