C++实现二叉搜索书(参考算法导论)

  1 #include <iostream>
  2 using namespace std;
  3 
  4 struct node 
  5 {
  6     // 数据域
  7     int data;
  8 
  9     // 左节点
 10     node *lc;
 11 
 12     // 右结点
 13     node *rc;
 14 
 15     // 构造函数
 16     node()
 17         : data(0)
 18         , lc(NULL)
 19         , rc(NULL)
 20     {
 21     }
 22 };
 23 
 24 
 25 // bst
 26 class bstree
 27 {
 28 public:
 29     enum
 30     {
 31         hmax_size_32767     = 32767,
 32         hmin_size_0         = 0,
 33     };
 34 
 35 public:
 36 
 37     // 构造函数
 38     bstree()
 39         : root(NULL)
 40         , size(0)
 41     {
 42     }
 43 
 44     // 析构函数
 45     virtual ~bstree(){}
 46     
 47     int get_size()
 48     {
 49         return size;
 50     }
 51 
 52     // 插入结点
 53     void insert_node(int data)
 54     {
 55         int cur_size = get_size();
 56         if (hmax_size_32767 == cur_size)
 57         {
 58             cout << "insert node error, the size of the tree is max" << endl;
 59             return ;
 60         }
 61         root = insert(root, data);
 62     }
 63 
 64     // 先序遍历(前序遍历)
 65     void pre_order()
 66     {
 67         pre_order_traverse(root);
 68     }
 69 
 70     // 中序遍历
 71     void in_order()
 72     {
 73         in_order_traverse(root);
 74     }
 75 
 76     // 后序遍历
 77     void post_order()
 78     {
 79         post_order_traverse(root);
 80     }
 81 
 82     /*
 83         查找某个结点
 84         int key - 查找结果
 85 
 86         返回值:
 87             NULL : 可能为root为空 或者 没有找到
 88             != NULL, 找到结点
 89     */
 90     node* query(int key)
 91     {
 92         if (NULL == root)
 93         {
 94             cout << "query error, root = null" << endl;
 95             return NULL;
 96         }
 97 
 98         return query_node(root, key);
 99     }
100 
101     // 删除树
102     void remove_all()
103     {
104         if (NULL == root)
105         {
106             cout << "remove all failed, root = null" << endl;
107             return;
108         }
109         
110         remove_all(root);
111 
112         int cur_size = get_size();
113         if (0 == cur_size)
114             root = NULL;
115     }
116 
117     // 删除某个结点
118     void remove_node(int del_data)
119     {
120         if (NULL == root)
121         {
122             cout << "remove node error, root = null" << endl;
123             return;
124         }
125 
126         node *parent_node   = NULL;
127         node *del_node      = root;
128 
129         // 找到删除结点的父节点与删除结点
130         while (del_node)
131         {
132             if (del_data == del_node->data)
133                 break;
134             else if (del_data > del_node->data)
135             {
136                 parent_node = del_node;
137                 del_node    = del_node->rc;
138             }
139             else if (del_data < del_node->data)
140             {
141                 parent_node = del_node;
142                 del_node = del_node->lc;
143             }
144         }
145 
146         // 若没有找到要删除的结点
147         if (NULL == del_node)
148         {
149             cout << "remove node error, " << del_data << " was not find" << endl;
150             return;
151         }
152 
153         // 1、若删除的结点没有左子树和右子树
154         if ( (NULL == del_node->lc) && (NULL == del_node->rc)  )
155         {
156             // 为什么要先判断根结点,因为根结点的父节点找不到,结果为NULL,
157             // 1.1 可能只有一个根结点, 将root释放值为空
158             if (del_node == root)
159             {
160                 root = NULL;
161                 delete del_node;
162                 del_node = NULL;
163 
164                 dec_size();
165                 return;
166             }
167 
168             // 1.2 非根结点,那就是叶子结点了, 将父节点指向删除结点的分支指向NULL
169             if  (del_node == parent_node->lc)
170                 parent_node->lc = NULL;
171             else if (del_node == parent_node->rc)
172                 parent_node->rc  = NULL;
173 
174             // 释放结点
175             delete del_node;
176             del_node = NULL;
177             dec_size();
178         }
179 
180         // 2、若删除结点只有左孩子,没有右孩子
181         else if ( (NULL != del_node->lc) && (NULL == del_node->rc) )
182         {
183             // 2.1 删除结点为根结点,则将删除结点的左孩子替代当前删除结点
184             if (del_node == root)
185             {
186                 root = root->lc;
187             }
188             // 2.2 其他结点,将删除结点的左孩子作为父节点的左孩子
189             else
190             {
191                 if (parent_node->lc == del_node)
192                     parent_node->lc = del_node->lc;
193                 else if (parent_node->rc == del_node)
194                     parent_node->rc = del_node->lc;
195             }
196 
197             delete del_node;
198             del_node = NULL;
199 
200             dec_size();
201         }
202 
203         // 3、若删除结点只有右孩子
204         else if ( (NULL == del_node->lc) && (NULL != del_node->rc) )
205         {
206             // 3.1 若为根结点
207             if (root == del_node)
208             {
209                 root = root->rc;
210             }
211             else
212             {
213                 if (del_node == parent_node->lc)
214                     parent_node->lc = del_node->rc;
215                 else if (del_node == parent_node->rc)
216                     parent_node->rc = del_node->rc;
217             }
218 
219             delete del_node;
220             del_node = NULL;
221 
222             dec_size();
223         }
224 
225         // 4、若删除结点既有左孩子,又有右孩子,需要找到删除结点的后继结点作为根结点
226         else if ( (NULL != del_node->lc) && (NULL != del_node->rc) )
227         {
228             node *successor_node = del_node->rc;
229             parent_node = del_node;
230 
231             while (successor_node->lc)
232             {
233                 parent_node = successor_node;
234                 successor_node = successor_node->lc;
235             }
236 
237             // 交换后继结点与当前删除结点的数据域
238             del_node->data = successor_node->data;
239             // 将指向后继结点的父节点的孩子设置后继结点的右子树
240             if (successor_node == parent_node->lc)
241                 parent_node->lc = successor_node->rc;
242             else if (successor_node == parent_node->rc)
243                 parent_node->rc = successor_node->rc;
244 
245             // 删除后继结点
246             del_node = successor_node;
247             delete del_node;
248             del_node = NULL;
249 
250             dec_size();
251         }
252     }
253 
254     // 返回以proot为根结点的最小结点
255     node *get_min_node(node *proot)
256     {
257         if (NULL == proot->lc)
258             return proot;
259 
260         return get_min_node(proot->lc);
261     }
262 
263     // 返回以proo为根节点的最大结点
264     node *get_max_node(node *proot)
265     {
266         if (NULL == proot->rc)
267             return proot;
268         
269         return get_max_node(proot->rc);
270     }
271 
272     // 返回根节点
273     node *get_root_node()
274     {
275         return root;
276     }
277 
278     // 返回proot结点的父节点
279     node *get_parent_node(int key)
280     {
281         // 当前结点
282         node *cur_node = NULL;
283         // 父节点
284         node *parent_node = NULL;
285 
286         cur_node = root;
287 
288         // 标记是否找到
289         bool is_find = false;
290         while (cur_node)
291         {
292             if (key == cur_node->data)
293             {
294                 is_find = true;
295                 break;
296             }
297 
298             // 因为比当前结点的值还要小,所以需要查找当前结点的左子树
299             else if (key < cur_node->data)
300             {
301                 parent_node = cur_node;
302                 cur_node = cur_node->lc;
303             }
304             // 同上, 查找当前结点的右子树
305             else if (key > cur_node->data)
306             {
307                 parent_node = cur_node;
308                 cur_node    = cur_node->rc;
309             }
310         }
311 
312         return (true == is_find)?  parent_node :  NULL; 
313     }
314 
315     // 查找某个结点为根节点的最结点
316 
317 private:
318 
319 
320     //查找某个值
321     node *query_node(node *proot, int key)
322     {
323         if (NULL == proot)
324         {
325             return proot;
326         }
327 
328         if (proot->data == key)
329             return proot;
330         else if (proot->data > key)
331         {
332             return query_node(proot->lc, key);
333         }
334         else if (proot->data < key)
335         {
336             return query_node(proot->rc, key);
337         }
338         
339         return NULL;
340     }
341 
342     // 后序遍历删除所有结点
343     void remove_all(node *proot)
344     {
345         if (NULL != proot)
346         {
347             remove_all(proot->lc);
348             remove_all(proot->rc);
349             delete proot;
350 
351             dec_size();
352         }
353     }
354 
355     // 先序遍历
356     void pre_order_traverse(node *proot)
357     {
358         if (NULL != proot)
359         {
360             cout << proot->data << ",   "; 
361             pre_order_traverse(proot->lc);
362             pre_order_traverse(proot->rc);
363         }
364     }
365 
366     // 中序遍历
367     void in_order_traverse(node *proot)
368     {
369         if (NULL != proot)
370         {
371             in_order_traverse(proot->lc);
372             cout << proot->data << ",   "; 
373             in_order_traverse(proot->rc);
374         }
375     }
376 
377     // 后续遍历
378     void post_order_traverse(node *proot)
379     {
380         if (NULL != proot)
381         {
382             post_order_traverse(proot->lc);
383             post_order_traverse(proot->rc);
384             cout << proot->data << ",   ";
385         }
386     }
387 
388     // 插入结点
389     node *insert(node *proot, int data)
390     {
391         // 结点不存在, 则创建
392         if (NULL == proot)
393         {
394             node *new_node = new(std::nothrow) node;
395             if (NULL != new_node)
396             {
397                 new_node->data = data;
398                 proot = new_node;
399                 
400                 // 结点+1;
401                 add_size();
402             }
403 
404             return proot;
405         }
406 
407         //  插入值比当前结点值还要小, 则应该插入到当前节点的左边
408         if (proot->data > data)
409         {
410             proot->lc = insert(proot->lc, data);
411         }
412         // 插入之比当前结点值还要打,则应该插入到当前结点的右边
413         else if (proot->data < data)
414         {
415             proot->rc = insert(proot->rc, data);
416         }
417 
418         // 相等,则不插入结点。
419 
420         return proot;
421     }
422 
423     // size + 1
424     void add_size()
425     {
426         if (hmax_size_32767 == size)
427             return ;
428         size++;
429     }
430 
431     // size - 1
432     void dec_size()
433     {
434         if ( hmin_size_0 == size)
435         {
436             return ;
437         }
438 
439         size--;
440     }
441 
442 private:
443     // 根结点
444     node *root;
445 
446     // 当前树的结点个数
447     int size;
448 };
449 
450 
451 
452 // 测试代码
453 int main()
454 {
455 
456     bstree tree;
457 
458     //
459     tree.insert_node(50);
460 
461     tree.insert_node(30);
462     tree.insert_node(10);
463     tree.insert_node(0);
464     tree.insert_node(20);
465     tree.insert_node(40);
466 
467     tree.insert_node(70);
468     tree.insert_node(90);
469     tree.insert_node(100);
470     tree.insert_node(60);
471     tree.insert_node(80);
472 
473     // 前序遍历
474     cout << "前序遍历" << endl;
475     tree.pre_order();
476     cout << endl;
477 
478     // 中序遍历
479     cout << "中序遍历" << endl;
480     tree.in_order();
481     cout << endl;
482 
483     // 后序遍历
484     cout << "后序遍历" << endl;
485     tree.post_order();
486     cout << endl;
487 
488     cout << "删除结点开始,结束请输入10086" << endl;
489 
490     int del_key = 0;
491 
492     while (true)
493     {
494         cout << "输入删除结点值 = ";
495         cin >> del_key;
496         if (10086 == del_key)
497             break;
498 
499         tree.remove_node(del_key);
500 
501         cout << "删除后,结点个数 = " << tree.get_size() << endl;
502         cout << "删除后, 中序遍历结果:" ;// << endl;
503         tree.in_order();
504         cout << endl << endl;
505     }
506 
507     tree.remove_all();
508 
509     return 0;
510 }

 

参考:《算法导论》

参考博文:https://www.cnblogs.com/fivestudy/p/10340647.html

 

!!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!!

作者:mohist

 

posted @ 2019-03-14 23:20  mohist  阅读(347)  评论(0编辑  收藏  举报