二叉查找树(BST)的实现(C++)
2009-05-06 21:35 Robin1986 阅读(1860) 评论(1) 编辑 收藏 举报二叉搜索树的实现
1//二叉搜索树的实现,其原理参见《算法导论第二版》第151页。
2
3#ifndef BST_H
4#define BST_H
5
6#include <iostream>
7#include <stdexcept>
8
9namespace NTCI
10{
11 template<typename Type>
12 class BST
13 {
14 public:
15 struct Node
16 {
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 else
56 removed = Successor(link);
57
58 // 待删除的元素至多只有一个子结点。
59 Link child = 0;
60 if (link->left != 0)
61 child = removed->left;
62 else
63 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 else
76 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 else
181 InsertBST(root->left, n);
182 }
183 else
184 {
185 if (root->right == 0)
186 {
187 n->parent = root;
188 root->right = n;
189 }
190 else
191 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 else
203 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_H
266
1//二叉搜索树的实现,其原理参见《算法导论第二版》第151页。
2
3#ifndef BST_H
4#define BST_H
5
6#include <iostream>
7#include <stdexcept>
8
9namespace NTCI
10{
11 template<typename Type>
12 class BST
13 {
14 public:
15 struct Node
16 {
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 else
56 removed = Successor(link);
57
58 // 待删除的元素至多只有一个子结点。
59 Link child = 0;
60 if (link->left != 0)
61 child = removed->left;
62 else
63 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 else
76 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 else
181 InsertBST(root->left, n);
182 }
183 else
184 {
185 if (root->right == 0)
186 {
187 n->parent = root;
188 root->right = n;
189 }
190 else
191 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 else
203 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_H
266
测试代码
1#include <iostream>
2#include <cassert>
3#include <stdexcept>
4#include "BST.h"
5
6using namespace std;
7using namespace NTCI;
8
9int main()
10{
11 try
12 {
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
1#include <iostream>
2#include <cassert>
3#include <stdexcept>
4#include "BST.h"
5
6using namespace std;
7using namespace NTCI;
8
9int main()
10{
11 try
12 {
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了~
欢迎大家就程序正确性以及代码风格等方面提出建议~