二叉搜索树的实现
1
//二叉搜索树的实现,其原理参见《算法导论第二版》第151页。
2![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
#ifndef BST_H
4
#define BST_H
5![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
#include <iostream>
7
#include <stdexcept>
8![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
9
namespace NTCI
10![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
11
template<typename Type>
12
class BST
13![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
14
public:
15
struct Node
16![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
17
Type item;
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![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
BST(Link r = 0) : root(r)
{}
26
template<typename InputIterator>
27
BST(InputIterator start, InputIterator end) : root(0)
28![ExpandedSubBlockStart.gif](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 ~BST()
34![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
35
Clear();
36
}
37
void Insert(Type item)
38![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
39
Link n = new Node();
40
n->item = item;
41
InsertBST(root, n);
42
}
43![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
44
Link Remove(Link link)
45![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
46
// 删除空节点时抛出参数无效的异常。
47
if (link == 0)
48
throw std::invalid_argument("待删除的结点为空");
49![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
50
// 先确定将要被删除的结点。如果结点只有一个或零个子结点,则原元素将被删除,
51
// 否侧其后继结点将被删除。
52
Link removed;
53
if (link->left == 0 || link->right == 0)
54
removed = link;
55
else
56
removed = Successor(link);
57![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
58
// 待删除的元素至多只有一个子结点。
59
Link child = 0;
60
if (link->left != 0)
61
child = removed->left;
62
else
63
child = removed->right;
64![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
65
// 先设置子结点的新的父节点。
66
if (child != 0)
67
child->parent = removed->parent;
68![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
69
// 如果待删除的结点为根节点,直接将根结点设置为子结点,
70
if (removed->parent == 0)
71
root = child;
72
// 否则将待删除结点的父节点的子结点指向待删除结点的子结点。
73
else if (removed == removed->parent->left)
74
removed->parent->left = child;
75
else
76
removed->parent->right = child;
77![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
78
// 如果原结点和被删除的结点不同,则说明原结点具有两个子结点,此时需要将
79
// 被删除结点的值复制到原结点。
80
if (link != removed)
81
link->item = removed->item;
82![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
83
return removed;
84
}
85![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
86
Link Remove(Type item)
87![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
88
Link link = Search(item);
89
return Remove(link);
90
}
91![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
92
Link Search(Type item)
93![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
94
return SearchBST(root, item);
95
}
96![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
97
int Maximum()
98![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
99
Link max = MaximumBST(root);
100
if (max == 0)
101
throw std::out_of_range("二叉搜索树为空");
102
return max->item;
103
}
104![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
105
int Minimun()
106![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
107
Link min = MinimunBST(root);
108
if (min == 0)
109
throw std::out_of_range("二叉搜索树为空");
110
return min->item;
111
}
112![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
113
void InorderWalk(std::ostream& out)
114![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
115
InorderWalkBST(root, out);
116
}
117![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
118
Link Successor(Link link)
119![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
120
// 如果右子结点不为空,则返回右子树的最小结点,
121
if (link->right != 0)
122
return MinimunBST(link->right);
123![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
124
// 否则后继元素是一个祖先结点,该结点的左子结点也是祖先结点。
125
Link p = link->parent;
126
while (p != 0 && link == p->right)
127![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
128
link = p;
129
p = link->parent;
130
}
131![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
132
return p;
133
}
134![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
135
Link Predecessor(Link link)
136![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
137
if (link->left != 0)
138
return MaximumBST(link->left);
139![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
140
Link p = link->parent;
141
while (p != 0 && link == p->left)
142![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
143
link = p;
144
p = link->parent;
145
}
146![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
147
return p;
148
}
149![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
150
int Heigth()
151![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
152
return HeightBST(root);
153
}
154![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
155
int Length()
156![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
157
return LengthBST(root);
158
}
159![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
160
void Clear()
161![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
162
ClearBST(root);
163
}
164![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
165
void InsertBST(Link& root, Link n)
166![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
167
if (root == 0)
168![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
169
root = n;
170
return;
171
}
172![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
173
if (n->item < root->item)
174![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
175
if (root->left == 0)
176![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
177
n->parent = root;
178
root ->left = n;
179
}
180
else
181
InsertBST(root->left, n);
182
}
183
else
184![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
185
if (root->right == 0)
186![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
187
n->parent = root;
188
root->right = n;
189
}
190
else
191
InsertBST(root->right, n);
192
}
193![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
194
}
195
private:
196
Link SearchBST(Link root, Type item)
197![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
198
if (root == 0 || root->item == item)
199
return root;
200
if (root->item > item)
201
return SearchBST(root->left, item);
202
else
203
return SearchBST(root->right, item);
204
}
205![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
206
void InorderWalkBST(Link root, std::ostream& out)
207![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
208
if (root == 0)
209
return;
210![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
211
InorderWalkBST(root->left, out);
212
out << root->item << " ";
213
InorderWalkBST(root->right, out);
214
}
215![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
216
Link MaximumBST(Link link)
217![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
218
while (link->right != 0)
219
link = link->right;
220
return link;
221
}
222![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
223
Link MinimunBST(Link link)
224![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
225
while (link->left != 0)
226
link = link->left;
227
return link;
228
}
229![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
230
int HeightBST(Link root)
231![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
232
if (root == 0)
233
return 0;
234![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
235
int lh, rh;
236
lh = HeightBST(root->left);
237
rh = HeightBST(root->right);
238
return std::max(lh, rh) + 1;
239
}
240![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
241![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
242
int LengthBST(Link root)
243![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
244
if (root == 0)
245
return 0;
246
return LengthBST(root->left) + LengthBST(root->right) + 1;
247
}
248![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
249
void ClearBST(Link& root)
250![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
251
if (root == 0)
252
return;
253
ClearBST(root->left);
254
ClearBST(root->right);
255
delete root;
256![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
257
root = 0;
258
}
259![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
260
private:
261
Link root;
262
};
263
}
264![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
265
#endif // BST_H
266
测试代码
1
#include <iostream>
2
#include <cassert>
3
#include <stdexcept>
4
#include "BST.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![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
11
try
12![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
int array[] =
{5, 4, 7, 2, 6, 8};
14
BST<int> bst(array, array + 6);
15![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
cout << "排序后:";
17
bst.InorderWalk(cout);
18
cout << endl;
19![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
bst.Remove(9);
28![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
link = bst.Search(7);
30
assert(link->item == 7);
31![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
32
link = bst.Remove(link);
33
delete link;
34
assert(bst.Length() == 5);
35
cout << "删除元素7后:";
36
bst.InorderWalk(cout);
37
cout << endl;
38![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
39
bst.Clear();
40
assert(bst.Length() == 0);
41
}
42
catch (exception& e)
43![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
44
cout << "发生异常:" << e.what() << endl;
45
}
46![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
47
return 0;
48
}
49
要实现随机构造的二叉查找树很容易,先调用标准库的random_shuffle函数对数组进行随机重排,然后再构造二叉搜索树就OK了~
欢迎大家就程序正确性以及代码风格等方面提出建议~