二叉樹之二叉搜索樹(BSTree)

二叉搜索樹(Binary Search Tree)node

  引用:https://www.cnblogs.com/skywang12345/linux

  詳解之後再補充。。。ios

  代碼含註釋,下面是輸出效果(msys2)git

 

代碼github

開發環境:Qt Creator 4.8.2  Mingw64 7.3  windows 8.1windows

完整代碼:https://github.com/Duacai/Data-Structure-and-Algorithms/tree/master/Data-Structure/Tree/BSTreepost

BSTree.h
ui

  1 #ifndef BSTREE_H
  2 #define BSTREE_H
  3 
  4 #include <iostream>
  5 #include <queue>
  6 
  7 using namespace std;
  8 
  9 namespace Viclib
 10 {
 11 
 12 template < typename T >
 13 class BSTNode
 14 {
 15 public:
 16     T mKey;
 17     BSTNode<T>    *mLeft;
 18     BSTNode<T>    *mRight;
 19     BSTNode<T>    *mParent;
 20 
 21     BSTNode() = delete;
 22     BSTNode(const T& key, BSTNode<T> *left, BSTNode<T> *right, BSTNode<T> *parent);
 23     BSTNode(const BSTNode<T>& tree) = delete;
 24     BSTNode(BSTNode<T> && tree);
 25     BSTNode<T>& operator = (const BSTNode<T>& tree) = delete;
 26     BSTNode<T>& operator = (BSTNode<T> && tree);
 27     virtual ~BSTNode();
 28 };
 29 
 30 template < typename T >
 31 BSTNode<T>::BSTNode(const T& key, BSTNode<T> *left, BSTNode<T> *right, BSTNode<T> *parent) :
 32     mKey(key), mLeft(left), mRight(right), mParent(parent)
 33 {
 34 }
 35 
 36 template < typename T >
 37 BSTNode<T>::BSTNode(BSTNode<T> && tree)
 38 {
 39     mLeft = tree.mLeft;
 40     mRight = tree.mRight;
 41     mParent = tree.mParent;
 42 
 43     tree->mLeft = nullptr;
 44     tree->mRight = nullptr;
 45     tree->mParent = nullptr;
 46 }
 47 
 48 template < typename T >
 49 BSTNode<T>& BSTNode<T>::operator = (BSTNode<T> && tree)
 50 {
 51     if ( this == &tree )
 52         return *this;
 53     
 54     delete mLeft;
 55     delete mRight;
 56     delete mParent;
 57     
 58     mLeft = tree->mLeft;
 59     mRight = tree->mRight;
 60     mParent = tree->mParent;
 61 
 62     return *this;
 63 }
 64 
 65 template < typename T >
 66 BSTNode<T>::~BSTNode()
 67 {
 68 }
 69 
 70 template < typename T >
 71 class BSTree
 72 {
 73 protected:
 74     BSTNode<T>* mRoot;
 75     size_t mCount;
 76 
 77     virtual void preOrder(BSTNode<T> *tree) const;                                // 深度優先的前、中、後序遍歷
 78     virtual void inOrder(BSTNode<T> *tree) const;
 79     virtual void postOrder(BSTNode<T> *tree) const;
 80 
 81     virtual void levelOrder(BSTNode<T> *tree) const;                            // 廣度優先
 82 
 83     virtual BSTNode<T>* search(BSTNode<T> *tree, const T& key) const;            // 遞歸版搜索
 84     virtual BSTNode<T>* iterativeSearch(BSTNode<T> *tree, const T& key) const;    // 非遞歸版搜索
 85 
 86     virtual BSTNode<T>* minimum(BSTNode<T> *tree) const;                        // 獲取最小最大值
 87     virtual BSTNode<T>* maximum(BSTNode<T> *tree) const;
 88 
 89     virtual BSTNode<T>* successor(BSTNode<T> *node) const;                        // 查找後繼,即大於又最接近node的節點
 90     virtual BSTNode<T>* predecessor(BSTNode<T> *node) const;                    // 查找前繼
 91 
 92     virtual void insert(BSTNode<T> *node);
 93     virtual BSTNode<T>* remove(BSTNode<T> *node);                                // 返回值用於刪除,返回值實際是替換結點
 94     virtual void destroy(BSTNode<T> *tree);
 95 
 96     void printTree(BSTNode<T> *tree, bool firstNode) const;                        // 打印樹,相似linux的tree命令
 97 
 98     virtual int height(BSTNode<T> *tree) const;                                    // 樹的高度
 99     virtual int degree(BSTNode<T> *tree) const;                                    // 結點的度數
100 
101 public:
102     BSTree();
103     BSTree(const BSTree<T>&) = default;
104     BSTree(BSTree<T> &&) = default;
105     BSTree<T>& operator = (const BSTree<T>&) = default;
106     BSTree<T>& operator = (BSTree<T> &&) = default;
107     virtual ~BSTree();
108 
109     virtual void preOrder() const;
110     virtual void inOrder() const;
111     virtual void postOrder() const;
112 
113     virtual void levelOrder() const;
114 
115     virtual BSTNode<T>* search(const T& key) const;
116     virtual BSTNode<T>* iterativeSearch(const T& key) const;
117 
118     virtual const T& minimum() const;
119     virtual const T& maximum() const;
120 
121     virtual void insert(const T& key);
122     virtual void remove(const T& key);
123     virtual void destroy();
124 
125     virtual int height() const;
126     virtual int degree() const;
127 
128     virtual size_t getCount() const;
129 
130     virtual const T& getRootKey() const;
131     virtual void printTree() const;
132 };
133 
134 template < typename T >
135 BSTree<T>::BSTree() : mRoot(nullptr), mCount(0)
136 {
137 }
138 
139 template < typename T >
140 void BSTree<T>::preOrder(BSTNode<T> *tree) const
141 {
142     if ( tree != nullptr )
143     {
144         cout << tree->mKey << " " << flush;
145         preOrder(tree->mLeft);
146         preOrder(tree->mRight);
147     }
148 }
149 
150 template < typename T >
151 void BSTree<T>::preOrder() const
152 {
153     preOrder(dynamic_cast<BSTNode<T>*>(this->mRoot));
154 }
155 
156 template < typename T >
157 void BSTree<T>::inOrder(BSTNode<T> *tree) const
158 {
159     if ( tree != nullptr )
160     {
161         inOrder(tree->mLeft);
162         cout << tree->mKey << " " << flush;
163         inOrder(tree->mRight);
164     }
165 }
166 
167 template < typename T >
168 void BSTree<T>::inOrder() const
169 {
170     inOrder(dynamic_cast<BSTNode<T>*>(this->mRoot));
171 }
172 
173 template < typename T >
174 void BSTree<T>::postOrder(BSTNode<T> *tree) const
175 {
176     if ( tree != nullptr )
177     {
178         postOrder(tree->mLeft);
179         postOrder(tree->mRight);
180         cout << tree->mKey << " " << flush;
181     }
182 }
183 
184 template < typename T >
185 void BSTree<T>::postOrder() const
186 {
187     postOrder(dynamic_cast<BSTNode<T>*>(this->mRoot));
188 }
189 
190 template < typename T >
191 void BSTree<T>::levelOrder(BSTNode<T> *tree) const
192 {
193     if ( tree != nullptr )
194     {
195         queue<BSTNode<T>*> tmp;
196         tmp.push(tree);
197 
198         while( tmp.size() > 0 )
199         {
200             BSTNode<T>* t = tmp.front();
201             tmp.pop();
202 
203             if ( t->mLeft != nullptr )
204                 tmp.push(t->mLeft);
205 
206             if ( t->mRight != nullptr )
207                 tmp.push(t->mRight);
208 
209             cout << t->mKey << " " << flush;
210         }
211     }
212 }
213 
214 template < typename T >
215 void BSTree<T>::levelOrder() const
216 {
217     levelOrder(dynamic_cast<BSTNode<T>*>(this->mRoot));
218 }
219 
220 template < typename T >
221 BSTNode<T>* BSTree<T>::search(BSTNode<T> *node, const T& key) const
222 {
223     if ( node == nullptr || node->mKey == key )
224     {
225         return node;
226     }
227     else if ( key < node->mKey )
228         return search(dynamic_cast<BSTNode<T>*>(node)->mLeft, key);
229     else
230         return search(dynamic_cast<BSTNode<T>*>(node)->mRight, key);
231 }
232 
233 template < typename T >
234 BSTNode<T>* BSTree<T>::search(const T& key) const
235 {
236     return search(dynamic_cast<BSTNode<T>*>(this->mRoot), key);
237 }
238 
239 template < typename T >
240 BSTNode<T>* BSTree<T>::iterativeSearch(BSTNode<T>* node, const T& key) const
241 {
242     while ( (node != nullptr) && (node->mKey != key) )
243     {
244         if ( key < node->mKey )
245             node = node->mLeft;
246         else
247             node = node->mRight;
248     }
249 
250     return node;
251 }
252 
253 template < typename T >
254 BSTNode<T>* BSTree<T>::iterativeSearch(const T& value) const
255 {
256     return iterativeSearch(dynamic_cast<BSTNode<T>*>(this->mRoot), value);
257 }
258 
259 template < typename T >
260 BSTNode<T>* BSTree<T>::minimum(BSTNode<T>* tree) const
261 {
262     if ( tree == nullptr )
263         return nullptr;
264 
265     while ( tree->mLeft != nullptr )
266         tree = tree->mLeft;
267 
268     return tree;
269 }
270 
271 template < typename T >
272 const T& BSTree<T>::minimum() const
273 {
274     BSTNode<T> *p = minimum(dynamic_cast<BSTNode<T>*>(this->mRoot));
275 //    if ( p == nullptr )
276 //        THROW_EXCEPTION(EmptyTreeException, "The tree is empty ...");
277 
278     return p->mKey;
279 }
280 
281 template < typename T >
282 BSTNode<T>* BSTree<T>::maximum(BSTNode<T>* tree) const
283 {
284     if ( tree == nullptr )
285         return nullptr;
286 
287     while ( tree->mRight != nullptr )
288         tree = tree->mRight;
289 
290     return tree;
291 }
292 
293 template < typename T >
294 const T& BSTree<T>::maximum() const
295 {
296     BSTNode<T> *p = maximum(dynamic_cast<BSTNode<T>*>(this->mRoot));
297 //    if ( p == nullptr )
298 //        THROW_EXCEPTION(EmptyTreeException, "The tree is empty ...");
299 
300     return p->mKey;
301 }
302 
303 template < typename T >
304 BSTNode<T>* BSTree<T>::successor(BSTNode<T> *node) const    // 查找後繼
305 {
306     if ( node->mRight != nullptr )                            // 若是node有右孩子,則在它的右孩子裏面最小的是後繼
307     {
308         return minimum(node->mRight);
309     }
310 
311     BSTNode<T>* ret = node->mParent;                        // 若是node沒有右孩子,且它自身是左孩子,則它的父親是後繼
312     while ( (ret != nullptr) && (node == ret->mRight) )        // 若是node沒有右孩子,且它自身是右孩子,它的最近祖先是左孩子的,則這個祖先的父親就是後繼
313     {
314         node = ret;
315         ret = ret->mParent;
316     }
317 
318     return ret;
319 }
320 
321 template < typename T >
322 BSTNode<T>* BSTree<T>::predecessor(BSTNode<T>* node) const    // 查找前繼
323 {
324     if ( node->mLeft != nullptr )                            // 若是node有左孩子,則在它的左孩子裏面最大的是前繼
325         return maximum(node->mLeft);
326 
327     BSTNode<T>* ret = node->mParent;                        // 若是node沒有左孩子,且它自身是右孩子,則它的父親是後繼
328     while ( (ret != nullptr) && (node == ret->mLeft) )        // 若是node沒有左孩子,且它自身是左孩子,它的最近祖先是右孩子的,則這個祖先的父親就是後繼
329     {
330         node = ret;
331         ret = ret->mLeft;
332     }
333 
334     return ret;
335 }
336 
337 template < typename T >
338 void BSTree<T>::insert(BSTNode<T>* node)
339 {
340     BSTNode<T>* in = nullptr;                // 插入點
341     BSTNode<T>* parent = dynamic_cast<BSTNode<T>*>(this->mRoot);        // 插入點的父節點
342 
343     while ( parent != nullptr )                // 查找node的插入點
344     {
345         in = parent;
346         if ( node->mKey < in->mKey )        // 若是node結點小於插入點,則插入到左孩子分支
347             parent = parent->mLeft;
348         else if ( node->mKey > in->mKey )    // 若是node結點大於插入點,則插入到右孩子分支
349             parent = parent->mRight;
350         else                                // 若是數據等同則跳出
351             break;
352     }
353 
354     node->mParent = in;                    // 設置node結點的父親爲插入點
355     if ( in == nullptr )                // 若是插入點爲空,設node結點爲根節點
356         this->mRoot = node;
357     else if ( node->mKey < in->mKey )    // 若是node結點小於插入點,插入左邊
358         in->mLeft = node;
359     else if ( node->mKey > in->mKey )    // 若是node結點大於插入點,插入右邊
360         in->mRight = node;
361     else                                // 若是數據等同則直接替換並釋放插入的結點
362     {
363         in->mKey = node->mKey;
364         delete node;
365         return;
366     }
367 
368     ++this->mCount;                        // 結點統計,注意重複結點插入時不能增長
369 }
370 
371 template < typename T >
372 void BSTree<T>::insert(const T& key)
373 {
374     insert(new BSTNode<T>(key, nullptr, nullptr, nullptr));
375 }
376 
377 template < typename T >
378 BSTNode<T>* BSTree<T>::remove(BSTNode<T> *node)
379 {
380     BSTNode<T>* replace = nullptr;            // 代替結點
381     BSTNode<T>* del = nullptr;                // 刪除點
382 
383     if ( (node->mLeft == nullptr) || (node->mRight == nullptr) )    // 若是孩子不全,node就是刪除點,能夠直接用僅有的孩子代替
384         del = node;
385     else                                                            // 不然有兩個孩子,後繼就是刪除點(右子樹中最小的成員)
386     {
387         del = successor(node);                                        // 查找後繼
388         node->mKey = del->mKey;                                        // 直接用後繼key替換node的key
389     }
390 
391     if ( del->mLeft != nullptr )            // 若是有左孩子,則更新左孩子爲代替結點(若是if成立就只有左孩子)
392         replace = del->mLeft;
393     else                                    // 不然設右孩子爲代替結點
394         replace = del->mRight;
395 
396     if ( replace != nullptr )                // 若是代替結點不是空樹,更新代替結點的父親
397         replace->mParent = del->mParent;
398 
399     if ( del->mParent == nullptr )            // 若是結點是根節點且孩子不全,那就直接替換
400         this->mRoot = replace;
401     else if ( del == del->mParent->mLeft )    // 若是刪除點爲左孩子,則更新父節點的左孩子
402         del->mParent->mLeft = replace;
403     else                                    // 不然更新父節點的右孩子
404         del->mParent->mRight = replace;
405 
406     --this->mCount;
407 
408     return del;
409 }
410 
411 template < typename T >
412 void BSTree<T>::remove(const T& key)
413 {
414     BSTNode<T> *del = nullptr, *node;
415     del = search(dynamic_cast<BSTNode<T>*>(this->mRoot), key);
416 
417     if ( del != nullptr )                        // 找到的刪除點不爲空
418         if ( (node = remove(del)) != nullptr )    // 刪除node並返回代替結點
419             delete node;                        // 刪除代替結點
420 }
421 
422 template < typename T >
423 void BSTree<T>::destroy(BSTNode<T> *tree)
424 {
425     if ( tree == nullptr )
426         return;
427 
428     if ( tree->mLeft != nullptr )
429         destroy(tree->mLeft);
430 
431     if ( tree->mRight != nullptr )
432         destroy(tree->mRight);
433 
434     delete tree;
435     tree = nullptr;
436 }
437 
438 template < typename T >
439 void BSTree<T>::destroy()
440 {
441     destroy(dynamic_cast<BSTNode<T>*>(this->mRoot));
442     this->mRoot = nullptr;
443     this->mCount = 0;
444 }
445 
446 template < typename T >
447 int BSTree<T>::height(BSTNode<T>* node) const
448 {
449     int ret = 0;
450 
451     if( node != nullptr )
452     {
453         int lh = height(node->mLeft);
454         int rh = height(node->mRight);
455 
456         ret = ((lh > rh) ? lh : rh) + 1;
457     }
458 
459     return ret;
460 }
461 
462 template < typename T >
463 int BSTree<T>::height() const
464 {
465     int ret = 0;
466 
467     if( this->mRoot != nullptr )
468     {
469         ret = height(dynamic_cast<BSTNode<T>*>(this->mRoot));
470     }
471 
472     return ret;
473 }
474 
475 template < typename T >
476 int BSTree<T>::degree(BSTNode<T>* node) const
477 {
478     int ret = 0;
479 
480     if( node != nullptr )
481     {
482         BSTNode<T>* child[] = { node->mLeft, node->mRight };
483 
484         ret = (!!node->mLeft + !!node->mRight);        // 統計有效結點數,!!用於轉換成bool類型,若是是有效結點則爲1,不然爲0
485 
486         for(int i=0; (i<2) && (ret<2); i++)            // 若是兒子不足2個須要檢查
487         {
488             int d = degree(child[i]);
489 
490             if( ret < d )
491             {
492                 ret = d;
493             }
494         }
495     }
496 
497     return ret;
498 }
499 
500 template < typename T >
501 int BSTree<T>::degree() const
502 {
503     return degree(dynamic_cast<BSTNode<T>*>(this->mRoot));
504 }
505 
506 template < typename T >
507 size_t BSTree<T>::getCount() const
508 {
509     return this->mCount;
510 }
511 
512 template <typename T>
513 void BSTree<T>::printTree(BSTNode<T> *tree, bool firstNode) const
514 {
515     if ( tree == nullptr )
516         return;
517 
518     size_t height = this->height();                // 樹的高度
519     static bool *outTag = new bool[height]();    // 左邊是否還有結點的標記,初始化爲false
520     uint8_t static layer = 0;                    // 當前層數,根結點爲第一層
521     uint8_t i;
522     ++layer;
523 
524     if ( layer > 1 )                    // 若是不是根節點須要輸出特殊符號
525     {
526         for (i=1; i<layer-1; ++i )        // 根節點和最後一個結點不須要,因此從1至(layer-1)
527             if ( outTag[i] )            // 若是左邊還有結點
528                 cout << "|       ";
529             else
530                 cout << "        ";
531 
532         if ( firstNode == true )        // 判斷左右結點,非二叉樹須要另外處理
533             cout << "L-------" << flush;
534         else
535             cout << "R-------" << flush;
536     }
537     cout << tree->mKey << endl;
538 
539     if ( (tree->mRight) != nullptr )    // 先輸出右節點
540     {
541         if ( tree->mLeft != nullptr )    // 若是左邊還有結點須要作標記
542             outTag[layer] = true;
543         printTree(tree->mRight, false);    // false表示當前是右節點
544     }
545 
546     if ( tree->mLeft != nullptr )
547     {
548         outTag[layer] = false;            // 左結點左邊再也不有結點,恢復默認標記
549         printTree(tree->mLeft, true);
550     }
551 
552     --layer;                            // 結點回溯時高度須要減1
553 }
554 
555 template <typename T>
556 void BSTree<T>::printTree() const
557 {
558     printTree(dynamic_cast<BSTNode<T>*>(this->mRoot), false);    // 做爲根節點時,右參數無心義
559 }
560 
561 template < typename T >
562 const T& BSTree<T>::getRootKey() const
563 {
564     return this->mRoot->mKey;
565 }
566 
567 template < typename T >
568 BSTree<T>::~BSTree()
569 {
570     destroy();
571 }
572 
573 }
574 
575 #endif // BSTREE_H

main.cppthis

  1 #include <iostream>
  2 #include <iomanip>
  3 #include <cmath>
  4 
  5 #include "BSTree.h"
  6 
  7 #include "Times.h"
  8 
  9 using namespace std;
 10 using namespace Viclib;
 11 
 12 int main(int argc, char* argv[])
 13 {
 14     uint16_t layer = 8;    // 結點最小層數
 15 
 16     if ( argc == 2 && atoi(argv[1])>0 )
 17         layer = static_cast<uint8_t>(atoi(argv[1]));
 18     else {
 19         cout << "請輸入結點最小層數,注意內存大小" << log(RAND_MAX*RAND_MAX+1+RAND_MAX*2)/log(2) << endl;
 20         cin >> layer;
 21     }
 22 
 23     timingStart();                            // 啓動計時
 24 
 25     cout << endl;
 26 
 27     uint64_t const count = (1ull<<layer)-1;    // 結點數
 28     uint16_t speed;                            // 記錄插入和刪除的進度百分比(0~100)
 29 
 30     BSTree<uint64_t> *tree = new BSTree<uint64_t>();
 31 
 32     speed = 0;
 33     srand(static_cast<unsigned int>(time(nullptr)));
 34     while ( tree->getCount() < count )
 35     {
 36         tree->insert(static_cast<size_t>(rand()*rand()+1+RAND_MAX*2));    // 使用隨機值插入;若是是順序值,會退化成鏈表模式,且插入變慢
 37 
 38         if ( (tree->getCount()*100/count > speed) || (tree->getCount() == count) )    // 進度值出現變化或完成操做時才能輸出
 39         {
 40             speed = static_cast<uint16_t>(tree->getCount()*100/count);
 41             cout << "\r已添加:" << setw(3) << speed << '%' << flush;
 42         }
 43     }
 44     cout << endl;
 45 
 46     cout << "\n前序遍歷: ";
 47     tree->preOrder();
 48     cout << endl;
 49 
 50     cout << "\n中序遍歷: ";
 51     tree->inOrder();
 52     cout << endl;
 53 
 54     cout << "\n後續遍歷: ";
 55     tree->postOrder();
 56     cout << endl;
 57 
 58     cout << "\n廣度遍歷:";
 59     tree->levelOrder();
 60     cout << endl;
 61 
 62     cout << "\n最小值: " << tree->minimum();
 63     cout << "\n最大值: " << tree->maximum();
 64     cout << "\n樹高度 = " << tree->height();
 65     cout << "\n結點數= " << tree->getCount();
 66     cout << endl;
 67 
 68     cout << "\n輸出樹形信息:" << endl;
 69     tree->printTree();
 70     cout << endl;
 71 
 72     speed = 0;
 73     srand(static_cast<unsigned int>(time(nullptr)));
 74     while ( tree->getCount() )
 75     {
 76         uint64_t node;
 77 //        if ( tree->getCount()*100/count < 20 )            // 剩餘量太少時,隨機值命中有效結點的機率過低,從而致使刪除緩慢
 78             node = tree->getRootKey();
 79 //        else
 80 //            node = static_cast<size_t>(rand()*rand()+1+RAND_MAX*2);
 81 
 82         tree->remove(node);
 83 
 84         if ( ((count-tree->getCount())*100/count > speed) || (tree->getCount() == count) )
 85         {
 86             speed = static_cast<uint16_t>((count-tree->getCount())*100/count);
 87             cout << "\r已刪除:" << setw(3) << speed << '%' << flush;
 88         }
 89     }
 90     cout << endl;
 91 
 92     tree->destroy();
 93     delete tree;
 94     tree = nullptr;
 95 
 96     cout << endl;
 97     timingEnd();
 98 
 99     return 0;
100 }
相關文章
相關標籤/搜索