码迷,mamicode.com
首页 > 其他好文 > 详细

4、【树形结构】二叉查找树

时间:2018-10-12 16:01:28      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:let   val   set   中序遍历   delete   bin   并且   c++实现   参数   

一、二叉查找树简介

二叉查找树(Binary Search Tree),又被称为二叉搜索树。
它是特殊的二叉树:对于二叉树,假设x为二叉树中的任意一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。那么,这棵树就是二叉查找树。

在二叉查找树中:
  (1) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  (2) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  (3) 任意节点的左、右子树也分别为二叉查找树。
  (4) 没有键值相等的节点(no duplicate nodes)。

二、二叉查找树的C++实现

1. 节点和二叉查找树的定义

1.1 二叉查找树节点

 1 template <class T>
 2 class BSTNode{
 3     public:
 4         T key;            // 关键字(键值)
 5         BSTNode *left;    // 左孩子
 6         BSTNode *right;    // 右孩子
 7         BSTNode *parent;// 父结点
 8 
 9         BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r):
10             key(value),parent(),left(l),right(r) {}
11 };

BSTNode是二叉查找树的节点,它包含二叉查找树的几个基本信息:
  (1) key -- 它是关键字,是用来对二叉查找树的节点进行排序的。
  (2) left -- 它指向当前节点的左孩子。
  (3) right -- 它指向当前节点的右孩子。
  (4) parent -- 它指向当前节点的父结点。

1.2 二叉树操作

 1 template <class T>
 2 class BSTree {
 3     private:
 4         BSTNode<T> *mRoot;    // 根结点
 5 
 6     public:
 7         BSTree();
 8         ~BSTree();
 9 
10         // 前序遍历"二叉树"
11         void preOrder();
12         // 中序遍历"二叉树"
13         void inOrder();
14         // 后序遍历"二叉树"
15         void postOrder();
16 
17         // (递归实现)查找"二叉树"中键值为key的节点
18         BSTNode<T>* search(T key);
19         // (非递归实现)查找"二叉树"中键值为key的节点
20         BSTNode<T>* iterativeSearch(T key);
21 
22         // 查找最小结点:返回最小结点的键值。
23         T minimum();
24         // 查找最大结点:返回最大结点的键值。
25         T maximum();
26 
27         // 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。
28         BSTNode<T>* successor(BSTNode<T> *x);
29         // 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。
30         BSTNode<T>* predecessor(BSTNode<T> *x);
31 
32         // 将结点(key为节点键值)插入到二叉树中
33         void insert(T key);
34 
35         // 删除结点(key为节点键值)
36         void remove(T key);
37 
38         // 销毁二叉树
39         void destroy();
40 
41         // 打印二叉树
42         void print();
43     private:
44         // 前序遍历"二叉树"
45         void preOrder(BSTNode<T>* tree) const;
46         // 中序遍历"二叉树"
47         void inOrder(BSTNode<T>* tree) const;
48         // 后序遍历"二叉树"
49         void postOrder(BSTNode<T>* tree) const;
50 
51         // (递归实现)查找"二叉树x"中键值为key的节点
52         BSTNode<T>* search(BSTNode<T>* x, T key) const;
53         // (非递归实现)查找"二叉树x"中键值为key的节点
54         BSTNode<T>* iterativeSearch(BSTNode<T>* x, T key) const;
55 
56         // 查找最小结点:返回tree为根结点的二叉树的最小结点。
57         BSTNode<T>* minimum(BSTNode<T>* tree);
58         // 查找最大结点:返回tree为根结点的二叉树的最大结点。
59         BSTNode<T>* maximum(BSTNode<T>* tree);
60 
61         // 将结点(z)插入到二叉树(tree)中
62         void insert(BSTNode<T>* &tree, BSTNode<T>* z);
63 
64         // 删除二叉树(tree)中的结点(z),并返回被删除的结点
65         BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z);
66 
67         // 销毁二叉树
68         void destroy(BSTNode<T>* &tree);
69 
70         // 打印二叉树
71         void print(BSTNode<T>* tree, T key, int direction);
72 };

BSTree是二叉树。它包含二叉查找树的根节点和二叉查找树的操作。二叉查找树的操作中有许多重载函数,例如insert()函数,其中一个是内部接口,另一个是提供给外部的接口。

2 遍历

这里讲解前序遍历、中序遍历、后序遍历3种方式。

2.1 前序遍历
若二叉树非空,则执行以下操作:
  (1) 访问根结点;
  (2) 先序遍历左子树;
  (3) 先序遍历右子树。

前序遍历代码

 1 template <class T>
 2 void BSTree<T>::preOrder(BSTNode<T>* tree) const
 3 {
 4     if(tree != NULL)
 5     {
 6         cout<< tree->key << " " ;
 7         preOrder(tree->left);
 8         preOrder(tree->right);
 9     }
10 }
11 
12 template <class T>
13 void BSTree<T>::preOrder() 
14 {
15     preOrder(mRoot);
16 }

2.2 中序遍历

若二叉树非空,则执行以下操作:
  (1) 中序遍历左子树;
  (2) 访问根结点;
  (3) 中序遍历右子树。

中序遍历代码

 1 template <class T>
 2 void BSTree<T>::inOrder(BSTNode<T>* tree) const
 3 {
 4     if(tree != NULL)
 5     {
 6         inOrder(tree->left);
 7         cout<< tree->key << " " ;
 8         inOrder(tree->right);
 9     }
10 }
11 
12 template <class T>
13 void BSTree<T>::inOrder() 
14 {
15     inOrder(mRoot);
16 }

2.3 后序遍历

若二叉树非空,则执行以下操作:
  (1) 后序遍历左子树;
  (2) 后序遍历右子树;
  (3) 访问根结点。

后序遍历代码

 1 template <class T>
 2 void BSTree<T>::postOrder(BSTNode<T>* tree) const
 3 {
 4     if(tree != NULL)
 5     {
 6         postOrder(tree->left);
 7         postOrder(tree->right);
 8         cout<< tree->key << " " ;
 9     }
10 }
11 
12 template <class T>
13 void BSTree<T>::postOrder() 
14 {
15     postOrder(mRoot);
16 }

前驱和后继

节点的前驱:是该节点的左子树中的最大节点。
节点的后继:是该节点的右子树中的最小节点。

【完整示例】

BSTree.h

  1 #ifndef _BINARY_SEARCH_TREE_HPP_
  2 #define _BINARY_SEARCH_TREE_HPP_
  3 
  4 #include <iomanip>
  5 #include <iostream>
  6 using namespace std;
  7 
  8 template <class T>
  9 class BSTNode{
 10     public:
 11         T key;            // 关键字(键值)
 12         BSTNode *left;    // 左孩子
 13         BSTNode *right;    // 右孩子
 14         BSTNode *parent;// 父结点
 15 
 16         BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r):
 17             key(value),parent(),left(l),right(r) {}
 18 };
 19 
 20 template <class T>
 21 class BSTree {
 22     private:
 23         BSTNode<T> *mRoot;    // 根结点
 24 
 25     public:
 26         BSTree();
 27         ~BSTree();
 28 
 29         // 前序遍历"二叉树"
 30         void preOrder();
 31         // 中序遍历"二叉树"
 32         void inOrder();
 33         // 后序遍历"二叉树"
 34         void postOrder();
 35 
 36         // (递归实现)查找"二叉树"中键值为key的节点
 37         BSTNode<T>* search(T key);
 38         // (非递归实现)查找"二叉树"中键值为key的节点
 39         BSTNode<T>* iterativeSearch(T key);
 40 
 41         // 查找最小结点:返回最小结点的键值。
 42         T minimum();
 43         // 查找最大结点:返回最大结点的键值。
 44         T maximum();
 45 
 46         // 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。
 47         BSTNode<T>* successor(BSTNode<T> *x);
 48         // 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。
 49         BSTNode<T>* predecessor(BSTNode<T> *x);
 50 
 51         // 将结点(key为节点键值)插入到二叉树中
 52         void insert(T key);
 53 
 54         // 删除结点(key为节点键值)
 55         void remove(T key);
 56 
 57         // 销毁二叉树
 58         void destroy();
 59 
 60         // 打印二叉树
 61         void print();
 62     private:
 63         // 前序遍历"二叉树"
 64         void preOrder(BSTNode<T>* tree) const;
 65         // 中序遍历"二叉树"
 66         void inOrder(BSTNode<T>* tree) const;
 67         // 后序遍历"二叉树"
 68         void postOrder(BSTNode<T>* tree) const;
 69 
 70         // (递归实现)查找"二叉树x"中键值为key的节点
 71         BSTNode<T>* search(BSTNode<T>* x, T key) const;
 72         // (非递归实现)查找"二叉树x"中键值为key的节点
 73         BSTNode<T>* iterativeSearch(BSTNode<T>* x, T key) const;
 74 
 75         // 查找最小结点:返回tree为根结点的二叉树的最小结点。
 76         BSTNode<T>* minimum(BSTNode<T>* tree);
 77         // 查找最大结点:返回tree为根结点的二叉树的最大结点。
 78         BSTNode<T>* maximum(BSTNode<T>* tree);
 79 
 80         // 将结点(z)插入到二叉树(tree)中
 81         void insert(BSTNode<T>* &tree, BSTNode<T>* z);
 82 
 83         // 删除二叉树(tree)中的结点(z),并返回被删除的结点
 84         BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z);
 85 
 86         // 销毁二叉树
 87         void destroy(BSTNode<T>* &tree);
 88 
 89         // 打印二叉树
 90         void print(BSTNode<T>* tree, T key, int direction);
 91 };
 92 
 93 /*
 94  * 构造函数
 95  */
 96 template <class T>
 97 BSTree<T>::BSTree():mRoot(NULL)
 98 {
 99 }
100 
101 /*
102  * 析构函数
103  */
104 template <class T>
105 BSTree<T>::~BSTree()
106 {
107     destroy();
108 }
109 
110 /*
111  * 前序遍历"二叉树"
112  */
113 template <class T>
114 void BSTree<T>::preOrder(BSTNode<T>* tree) const
115 {
116     if(tree != NULL)
117     {
118         cout<< tree->key << " " ;
119         preOrder(tree->left);
120         preOrder(tree->right);
121     }
122 }
123 
124 template <class T>
125 void BSTree<T>::preOrder()
126 {
127     preOrder(mRoot);
128 }
129 
130 /*
131  * 中序遍历"二叉树"
132  */
133 template <class T>
134 void BSTree<T>::inOrder(BSTNode<T>* tree) const
135 {
136     if(tree != NULL)
137     {
138         inOrder(tree->left);
139         cout<< tree->key << " " ;
140         inOrder(tree->right);
141     }
142 }
143 
144 template <class T>
145 void BSTree<T>::inOrder()
146 {
147     inOrder(mRoot);
148 }
149 
150 /*
151  * 后序遍历"二叉树"
152  */
153 template <class T>
154 void BSTree<T>::postOrder(BSTNode<T>* tree) const
155 {
156     if(tree != NULL)
157     {
158         postOrder(tree->left);
159         postOrder(tree->right);
160         cout<< tree->key << " " ;
161     }
162 }
163 
164 template <class T>
165 void BSTree<T>::postOrder()
166 {
167     postOrder(mRoot);
168 }
169 
170 /*
171  * (递归实现)查找"二叉树x"中键值为key的节点
172  */
173 template <class T>
174 BSTNode<T>* BSTree<T>::search(BSTNode<T>* x, T key) const
175 {
176     if (x==NULL || x->key==key)
177         return x;
178 
179     if (key < x->key)
180         return search(x->left, key);
181     else
182         return search(x->right, key);
183 }
184 
185 template <class T>
186 BSTNode<T>* BSTree<T>::search(T key)
187 {
188     search(mRoot, key);
189 }
190 
191 /*
192  * (非递归实现)查找"二叉树x"中键值为key的节点
193  */
194 template <class T>
195 BSTNode<T>* BSTree<T>::iterativeSearch(BSTNode<T>* x, T key) const
196 {
197     while ((x!=NULL) && (x->key!=key))
198     {
199         if (key < x->key)
200             x = x->left;
201         else
202             x = x->right;
203     }
204 
205     return x;
206 }
207 
208 template <class T>
209 BSTNode<T>* BSTree<T>::iterativeSearch(T key)
210 {
211     iterativeSearch(mRoot, key);
212 }
213 
214 /*
215  * 查找最小结点:返回tree为根结点的二叉树的最小结点。
216  */
217 template <class T>
218 BSTNode<T>* BSTree<T>::minimum(BSTNode<T>* tree)
219 {
220     if (tree == NULL)
221         return NULL;
222 
223     while(tree->left != NULL)
224         tree = tree->left;
225     return tree;
226 }
227 
228 template <class T>
229 T BSTree<T>::minimum()
230 {
231     BSTNode<T> *p = minimum(mRoot);
232     if (p != NULL)
233         return p->key;
234 
235     return (T)NULL;
236 }
237 
238 /*
239  * 查找最大结点:返回tree为根结点的二叉树的最大结点。
240  */
241 template <class T>
242 BSTNode<T>* BSTree<T>::maximum(BSTNode<T>* tree)
243 {
244     if (tree == NULL)
245         return NULL;
246 
247     while(tree->right != NULL)
248         tree = tree->right;
249     return tree;
250 }
251 
252 template <class T>
253 T BSTree<T>::maximum()
254 {
255     BSTNode<T> *p = maximum(mRoot);
256     if (p != NULL)
257         return p->key;
258 
259     return (T)NULL;
260 }
261 
262 /*
263  * 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。
264  */
265 template <class T>
266 BSTNode<T>* BSTree<T>::successor(BSTNode<T> *x)
267 {
268     // 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
269     if (x->right != NULL)
270         return minimum(x->right);
271 
272     // 如果x没有右孩子。则x有以下两种可能:
273     // (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
274     // (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
275     BSTNode<T>* y = x->parent;
276     while ((y!=NULL) && (x==y->right))
277     {
278         x = y;
279         y = y->parent;
280     }
281 
282     return y;
283 }
284 
285 /*
286  * 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。
287  */
288 template <class T>
289 BSTNode<T>* BSTree<T>::predecessor(BSTNode<T> *x)
290 {
291     // 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
292     if (x->left != NULL)
293         return maximum(x->left);
294 
295     // 如果x没有左孩子。则x有以下两种可能:
296     // (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
297     // (01) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
298     BSTNode<T>* y = x->parent;
299     while ((y!=NULL) && (x==y->left))
300     {
301         x = y;
302         y = y->parent;
303     }
304 
305     return y;
306 }
307 
308 /*
309  * 将结点插入到二叉树中
310  *
311  * 参数说明:
312  *     tree 二叉树的根结点
313  *     z 插入的结点
314  */
315 template <class T>
316 void BSTree<T>::insert(BSTNode<T>* &tree, BSTNode<T>* z)
317 {
318     BSTNode<T> *y = NULL;
319     BSTNode<T> *x = tree;
320 
321     // 查找z的插入位置
322     while (x != NULL)
323     {
324         y = x;
325         if (z->key < x->key)
326             x = x->left;
327         else
328             x = x->right;
329     }
330 
331     z->parent = y;
332     if (y==NULL)
333         tree = z;
334     else if (z->key < y->key)
335         y->left = z;
336     else
337         y->right = z;
338 }
339 
340 /*
341  * 将结点(key为节点键值)插入到二叉树中
342  *
343  * 参数说明:
344  *     tree 二叉树的根结点
345  *     key 插入结点的键值
346  */
347 template <class T>
348 void BSTree<T>::insert(T key)
349 {
350     BSTNode<T> *z=NULL;
351 
352     // 如果新建结点失败,则返回。
353     if ((z=new BSTNode<T>(key,NULL,NULL,NULL)) == NULL)
354         return ;
355 
356     insert(mRoot, z);
357 }
358 
359 /*
360  * 删除结点(z),并返回被删除的结点
361  *
362  * 参数说明:
363  *     tree 二叉树的根结点
364  *     z 删除的结点
365  */
366 template <class T>
367 BSTNode<T>* BSTree<T>::remove(BSTNode<T>* &tree, BSTNode<T> *z)
368 {
369     BSTNode<T> *x=NULL;
370     BSTNode<T> *y=NULL;
371 
372     if ((z->left == NULL) || (z->right == NULL) )
373         y = z;
374     else
375         y = successor(z);
376 
377     if (y->left != NULL)
378         x = y->left;
379     else
380         x = y->right;
381 
382     if (x != NULL)
383         x->parent = y->parent;
384 
385     if (y->parent == NULL)
386         tree = x;
387     else if (y == y->parent->left)
388         y->parent->left = x;
389     else
390         y->parent->right = x;
391 
392     if (y != z)
393         z->key = y->key;
394 
395     return y;
396 }
397 
398 /*
399  * 删除结点(z),并返回被删除的结点
400  *
401  * 参数说明:
402  *     tree 二叉树的根结点
403  *     z 删除的结点
404  */
405 template <class T>
406 void BSTree<T>::remove(T key)
407 {
408     BSTNode<T> *z, *node;
409 
410     if ((z = search(mRoot, key)) != NULL)
411         if ( (node = remove(mRoot, z)) != NULL)
412             delete node;
413 }
414 
415 /*
416  * 销毁二叉树
417  */
418 template <class T>
419 void BSTree<T>::destroy(BSTNode<T>* &tree)
420 {
421     if (tree==NULL)
422         return ;
423 
424     if (tree->left != NULL)
425         return destroy(tree->left);
426     if (tree->right != NULL)
427         return destroy(tree->right);
428 
429     delete tree;
430     tree=NULL;
431 }
432 
433 template <class T>
434 void BSTree<T>::destroy()
435 {
436     destroy(mRoot);
437 }
438 
439 /*
440  * 打印"二叉查找树"
441  *
442  * key        -- 节点的键值
443  * direction  --  0,表示该节点是根节点;
444  *               -1,表示该节点是它的父结点的左孩子;
445  *                1,表示该节点是它的父结点的右孩子。
446  */
447 template <class T>
448 void BSTree<T>::print(BSTNode<T>* tree, T key, int direction)
449 {
450     if(tree != NULL)
451     {
452         if(direction==0)    // tree是根节点
453             cout << setw(2) << tree->key << " is root" << endl;
454         else                // tree是分支节点
455             cout << setw(2) << tree->key << " is " << setw(2) << key << "‘s "  << setw(12) << (direction==1?"right child" : "left child") << endl;
456 
457         print(tree->left, tree->key, -1);
458         print(tree->right,tree->key,  1);
459     }
460 }
461 
462 template <class T>
463 void BSTree<T>::print()
464 {
465     if (mRoot != NULL)
466         print(mRoot, mRoot->key, 0);
467 }
468 
469 #endif

mian.cpp

 1 #include <iostream>
 2 #include "BSTree.h"
 3 using namespace std;
 4 
 5 static int arr[]= {1,5,4,3,2,6};
 6 #define TBL_SIZE(a) ( (sizeof(a)) / (sizeof(a[0])) )
 7 
 8 int main()
 9 {
10     int i, ilen;
11     BSTree<int>* tree=new BSTree<int>();
12 
13     cout << "== 依次添加: ";
14     ilen = TBL_SIZE(arr);
15     for(i=0; i<ilen; i++) 
16     {
17         cout << arr[i] <<" ";
18         tree->insert(arr[i]);
19     }
20 
21     cout << "\n== 前序遍历: ";
22     tree->preOrder();
23 
24     cout << "\n== 中序遍历: ";
25     tree->inOrder();
26 
27     cout << "\n== 后序遍历: ";
28     tree->postOrder();
29     cout << endl;
30 
31     cout << "== 最小值: " << tree->minimum() << endl;
32     cout << "== 最大值: " << tree->maximum() << endl;
33     cout << "== 树的详细信息: " << endl;
34     tree->print();
35 
36     cout << "\n== 删除根节点: " << arr[3];
37     tree->remove(arr[3]);
38 
39     cout << "\n== 中序遍历: ";
40     tree->inOrder();
41     cout << endl;
42 
43     // 销毁二叉树
44     tree->destroy();
45 
46     return 0;
47 }

 

4、【树形结构】二叉查找树

标签:let   val   set   中序遍历   delete   bin   并且   c++实现   参数   

原文地址:https://www.cnblogs.com/Long-w/p/9778102.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!