二叉樹之紅黑樹(RBTree)

紅黑樹(RB-Tree)html

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

  詳解之後再補充。。。ios

紅黑樹和AVL樹6層模式下的最少結點數git

  經過圖能夠看到紅黑樹能夠實現更少的結點,反過來講就是一樣的結點數紅黑樹最大數高會超過AVL樹github

  https://www.cs.usfca.edu/~galles/visualization/Algorithms.html這個網站能夠測試動態效果,下圖就是截圖於此post

 

 

紅黑樹插入刪除步驟測試

 

輸出網站

代碼ui

其他代碼:https://github.com/Duacai/Data-Structure-and-Algorithms/tree/master/Data-Structure/Tree/RBTreespa

工程經過Qt Creator建立

RBTree.h

  1 #ifndef RBTREE_H
  2 #define RBTREE_H
  3 
  4 #include <iostream>
  5 #include <iomanip>
  6 #include <queue>
  7 
  8 using namespace std;
  9 
 10 namespace Viclib
 11 {
 12 
 13 enum RBTColor { RED, BLACK };
 14 
 15 template <typename T>
 16 class RBTNode
 17 {
 18 public:
 19     RBTColor mColor;
 20     T mKey;
 21     RBTNode<T>* mLeft;
 22     RBTNode<T>* mRight;
 23     RBTNode<T>* mParent;
 24 
 25     RBTNode(RBTColor color, T key, RBTNode<T>* left, RBTNode<T>* right, RBTNode<T>* parent) :
 26         mColor(color), mKey(key), mLeft(left), mRight(right), mParent(parent) {}
 27 };
 28 
 29 template <typename T>
 30 class RBTree
 31 {
 32 private:
 33     RBTNode<T>* mRoot;
 34     uint64_t mCount;
 35     uint16_t mHeight;
 36 
 37     void preOrder(RBTNode<T>* tree) const;
 38     void inOrder(RBTNode<T>* tree) const;
 39     void postOrder(RBTNode<T>* tree) const;
 40 
 41     void levelOrder(RBTNode<T>* tree) const;
 42 
 43     RBTNode<T>* search(RBTNode<T>* tree, T key) const;
 44     RBTNode<T>* iterativeSearch(RBTNode<T>* tree, T key) const;
 45 
 46     RBTNode<T>* minimum(RBTNode<T>* tree) const;
 47     RBTNode<T>* maximum(RBTNode<T>* tree) const;
 48 
 49     void lRotate(RBTNode<T>* &tree, RBTNode<T>* node) const;
 50     void rRotate(RBTNode<T>* &tree, RBTNode<T>* node) const;
 51 
 52     void insert(RBTNode<T>* &tree, RBTNode<T>* node);
 53     void insertFixUp(RBTNode<T>* &tree, RBTNode<T>* node);    // 插入修正紅黑樹
 54 
 55     void remove(RBTNode<T>* &tree, RBTNode<T> *del);
 56     void removeFixUp(RBTNode<T>* &tree, RBTNode<T>* del, RBTNode<T>* parent);    // 刪除修正紅黑樹(被刪除的是黑色)
 57 
 58     void printTree(RBTNode<T> const* const tree, bool firstNode) const;
 59 
 60     void destroy(RBTNode<T>* &tree);
 61     uint16_t max(uint16_t left, uint16_t right) const;
 62     uint16_t updateHeight(RBTNode<T> *node);
 63 
 64 public:
 65     RBTree();
 66     ~RBTree();
 67 
 68     void preOrder() const;
 69     void inOrder() const;
 70     void postOrder() const;
 71 
 72     void levelOrder() const;
 73 
 74     RBTNode<T>* search(T key) const;
 75     RBTNode<T>* iterativeSearch(T key) const;
 76 
 77     T const* minimum() const;
 78     T const* maximum() const;
 79 
 80     RBTNode<T>* successor(RBTNode<T>* node) const;
 81     RBTNode<T>* predecessor(RBTNode<T>* node) const;
 82 
 83     void insert(T key);
 84     bool remove(T key);
 85 
 86     void printTree() const;
 87 
 88     void destroy();
 89     uint64_t getCount() const;
 90     uint16_t getHeight(bool update = true);
 91     bool rootIsNullptr() const;
 92     T getRootKey() const;
 93     uint8_t setKeyStrLen();
 94 };
 95 
 96 template <typename T>
 97 RBTree<T>::RBTree() : mRoot(nullptr), mCount(0ull), mHeight(0)
 98 {
 99 }
100 
101 template <typename T>
102 RBTree<T>::~RBTree()
103 {
104     destroy();
105 }
106 
107 template <typename T>
108 void RBTree<T>::preOrder(RBTNode<T>* tree) const
109 {
110     if ( tree != nullptr )
111     {
112         cout << tree->mKey << " " << flush;
113         preOrder(tree->mLeft);
114         preOrder(tree->mRight);
115     }
116 }
117 
118 template <typename T>
119 void RBTree<T>::preOrder() const
120 {
121     preOrder(mRoot);
122     cout << endl;
123 }
124 
125 template <typename T>
126 void RBTree<T>::inOrder(RBTNode<T>* tree) const
127 {
128     if ( tree != nullptr )
129     {
130         inOrder(tree->mLeft);
131         cout << tree->mKey << " " << flush;
132         inOrder(tree->mRight);
133     }
134 }
135 
136 template <typename T>
137 void RBTree<T>::inOrder() const
138 {
139     inOrder(mRoot);
140     cout << endl;
141 }
142 
143 template <typename T>
144 void RBTree<T>::postOrder(RBTNode<T>* tree) const
145 {
146     if ( tree != nullptr )
147     {
148         postOrder(tree->mLeft);
149         postOrder(tree->mRight);
150         cout << tree->mKey << " " << flush;
151     }
152 }
153 
154 template <typename T>
155 void RBTree<T>::postOrder() const
156 {
157     postOrder(mRoot);
158     cout << endl;
159 }
160 
161 template <typename T>
162 void RBTree<T>::levelOrder(RBTNode<T>* tree) const
163 {
164     if ( tree != nullptr )
165     {
166         queue<RBTNode<T>*> tmp;
167         tmp.push(tree);
168 
169         while( tmp.size() > 0 )
170         {
171             RBTNode<T>* t = tmp.front();
172 
173             if ( t->mLeft != nullptr )
174                 tmp.push(t->mLeft);
175 
176             if ( t->mRight != nullptr )
177                 tmp.push(t->mRight);
178 
179             tmp.pop();
180 
181             cout << t->mKey << " " << flush;
182         }
183     }
184 }
185 
186 template <typename T>
187 void RBTree<T>::levelOrder() const
188 {
189     levelOrder(mRoot);
190     cout << endl;
191 }
192 
193 template <typename T>
194 RBTNode<T>* RBTree<T>::search(RBTNode<T>* tree, T key) const
195 {
196     if ( tree==nullptr || key==tree->mKey )
197         return tree;
198 
199     if ( key < tree->mKey )
200         return search(tree->mLeft, key);
201     else
202         return search(tree->mRight, key);
203 }
204 
205 template <typename T>
206 RBTNode<T>* RBTree<T>::search(T key) const
207 {
208     return search(mRoot, key);
209 }
210 
211 template <typename T>
212 RBTNode<T>* RBTree<T>::iterativeSearch(RBTNode<T>* tree, T key) const
213 {
214     while ( tree!=nullptr && key!=tree->mKey )
215     {
216         if ( key < tree->mKey )
217             tree = tree->mLeft;
218         else
219             tree = tree->mRight;
220     }
221 
222     return tree;
223 }
224 
225 template <typename T>
226 RBTNode<T>* RBTree<T>::iterativeSearch(T key) const
227 {
228     return iterativeSearch(mRoot, key);
229 }
230 
231 template <typename T>
232 RBTNode<T>* RBTree<T>::minimum(RBTNode<T>* tree) const
233 {
234     if ( tree == nullptr )
235         return nullptr;
236 
237     while ( tree->mLeft != nullptr )
238         tree = tree->mLeft;
239 
240     return tree;
241 }
242 
243 template <typename T>
244 T const* RBTree<T>::minimum() const
245 {
246     RBTNode<T>* ret = minimum(mRoot);
247     if ( ret != nullptr )
248         return &ret->mKey;
249 
250     return nullptr;
251 }
252 
253 template <typename T>
254 RBTNode<T>* RBTree<T>::maximum(RBTNode<T>* tree) const
255 {
256     if ( tree == nullptr )
257         return nullptr;
258 
259     while ( tree->mRight != nullptr )
260         tree = tree->mRight;
261 
262     return tree;
263 }
264 
265 template <typename T>
266 T const* RBTree<T>::maximum() const
267 {
268     RBTNode<T>* ret = maximum(mRoot);
269     if ( ret != nullptr )
270         return &ret->mKey;
271 
272     return nullptr;
273 }
274 
275 template <typename T>
276 RBTNode<T>* RBTree<T>::successor(RBTNode<T>* tree) const    // 查找tree的後繼,比tree大
277 {
278     if ( tree->right != nullptr )            // 在右節點查找最小結點
279         return minimum(tree->right);
280 
281     RBTNode<T>* p = tree->parent;
282     while ( p!=nullptr && tree==p->right )    // 父節點非空且本身是右節點就繼續尋找,直至本身是左結點或父節點爲空
283     {
284         tree = p;
285         p = p->parent;
286     }
287 
288     return p;
289 }
290 
291 template <typename T>
292 RBTNode<T>* RBTree<T>::predecessor(RBTNode<T>* tree) const    // 查找tree的前任,比tree小
293 {
294     if ( tree->left != nullptr )            // 在左結點查找最大結點
295         return maximum(tree->left);
296 
297     RBTNode<T>* p = tree->parent;
298     while ( p!=nullptr && tree==p->left )    // 父節點非空且本身是左結點就繼續尋找,直至本身是右節點或父節點爲空
299     {
300         tree = p;
301         p = p->parent;
302     }
303 
304     return p;
305 }
306 
307 /*    左旋
308  *    p                     p
309  *    |                     |
310  *   old                   new
311  *   / \     --(左旋)-->    / \
312  *  a  new                old c
313  *     / \                / \
314  *    B   c              a   B
315  */
316 template <typename T>
317 void RBTree<T>::lRotate(RBTNode<T>* &tree, RBTNode<T>* node) const    // 將右邊重的結點旋轉至左邊重
318 {                                                                    // 當前結點成爲右孩子的左孩子,右孩子的左孩子成爲本身的右孩子,右孩子則替換本身位置
319     RBTNode<T>* r = node->mRight;            // 新結點指向右節點
320 
321     node->mRight = r->mLeft;                    // 更新 【當前結點(舊結點)】 與 【右節點(新結點)的左孩子】 之間的關係
322     if ( r->mLeft != nullptr )
323         r->mLeft->mParent = node;
324 
325     r->mParent = node->mParent;                // 更新 父節點 和 新孩子 之間的關係
326     if ( node->mParent == nullptr )
327         tree = r;
328     else
329     {
330         if ( node == node->mParent->mLeft )        // 判斷並更新父節點的新孩子
331             node->mParent->mLeft = r;
332         else
333             node->mParent->mRight = r;
334     }
335 
336     r->mLeft = node;                            // 更新 新舊結點 之間的關係
337     node->mParent = r;
338 }
339 
340 /*    右旋
341  *      p                  p
342  *      |                  |
343  *     old                new
344  *     / \   --(右旋)-->   / \
345  *   new  c              a  old
346  *   / \                    / \
347  *  a   B                  B   c
348  */
349 template <typename T>
350 void RBTree<T>::rRotate(RBTNode<T>* &tree, RBTNode<T>* node) const
351 {
352     RBTNode<T>* l = node->mLeft;
353 
354     node->mLeft = l->mRight;
355     if ( l->mRight != nullptr )
356         l->mRight->mParent = node;
357 
358     l->mParent = node->mParent;
359     if ( node->mParent == nullptr )
360         tree = l;
361     else
362     {
363         if ( node == node->mParent->mLeft )
364             node->mParent->mLeft = l;
365         else
366             node->mParent->mRight = l;
367     }
368 
369     l->mRight = node;
370     node->mParent = l;
371 }
372 
373 template <typename T>
374 void RBTree<T>::insertFixUp(RBTNode<T>* &tree, RBTNode<T>* node)    // 插入修正紅黑樹
375 {
376     RBTNode<T> *parent, *gparent;    // 父結點,爺爺結點
377 
378     // node有父結點且父親是紅色(R紅色、B黑色、@插入結點)
379     while ( (parent = node->mParent) && (parent->mColor==RED) )
380     {
381         gparent = parent->mParent;
382 
383         if ( parent == gparent->mLeft )    // 父親是左孩子,叔叔是右孩子
384         {
385             {    // 叔叔有效且是紅色,while保證父親也是紅色
386                 RBTNode<T>* uncle = gparent->mRight;
387                 if ( uncle && uncle->mColor==RED )    // 父親是紅色,本身默認又是紅色,因此須要變色
388                 {                                    // 將父親和叔叔設爲黑結點,爺爺設爲紅節點;
389                     uncle->mColor = BLACK;    //   B              R
390                     parent->mColor = BLACK;    // R   R        B   B
391                     gparent->mColor = RED;    // R(@)            R(@)    // 不區分本身是左孩子仍是右孩子
392                     node = gparent;                    // node指向爺爺後向上再判斷其它結點是否須要平衡
393                     continue;
394                 }
395             }
396             // 父親爲紅色時若是叔叔不是紅色,則叔叔必是黑色葉子,且父親的子女也全是葉子;由於父親必須有一個葉子子結點才能插入,若是叔叔不是葉子或父親的兒子不全是葉子則沒法平衡
397             {    // 叔叔爲空,本身是紅色父親的右孩子,旋轉成左孩子(父子身份也交換,且父子仍爲紅色)
398                 if ( parent->mRight == node )// 紅節點的子結點若有葉子則全是葉子,不然不平衡;父親以前沒有子結點則父親無兄弟
399                 {
400                     RBTNode<T>* tmp;
401                     lRotate(tree, parent);    // 左旋後node替換父親,父親則成爲本身的左孩子,變成左左模式,左左都是紅色
402                     tmp = parent;            // 旋轉後修正父子指針位置,父子互換
403                     parent = node;            //     B        B          B
404                     node = tmp;                //    R        R(@)       R
405                 }                            //     R(@)    R          R(@)
406             }
407 
408             {    // 叔叔爲空,本身是紅色父親的左孩子
409                 parent->mColor = BLACK;        //     B        R          B
410                 gparent->mColor = RED;        //    R        B        R(@)   R
411                 rRotate(tree, gparent);        // R(@)        R(@)
412             }
413         }
414         else                        // 父親是右孩子,伯父是左孩子
415         {
416             {    // 伯父有效且是紅色,while保證父親也是紅色
417                 RBTNode<T>* uncle = gparent->mLeft;
418                 if ( uncle && uncle->mColor==RED )
419                 {
420                     uncle->mColor = BLACK;    //     B            R
421                     parent->mColor = BLACK;    // R   R         B   B
422                     gparent->mColor = RED;    //       R(@)            R(@)
423                     node = gparent;
424                     continue;
425                 }
426             }
427 
428             {    // 伯父爲空或爲黑色,本身是紅色父親的左孩子,旋轉成右孩子(父子身份也交換,且父子仍爲紅色)
429                 if ( parent->mLeft == node )
430                 {
431                     RBTNode<T>* tmp;
432                     rRotate(tree, parent);
433                     tmp = parent;            // B         B       B
434                     parent = node;            //  R        R(@)     R
435                     node = tmp;                // R(@)          R       R(@)
436                 }
437             }
438 
439             {    // 伯父爲空或爲黑色,本身是紅色父親的右孩子
440                 parent->mColor = BLACK;        // B         R            B
441                 gparent->mColor = RED;        //    R        #       R       R(@)
442                 lRotate(tree, gparent);        //     R(@)      R(@)
443             }
444         }
445     }
446 
447     tree->mColor = BLACK;    // 若是沒有父節點則當前結點就是根節點;父節點爲黑則這條語句無心義
448 }
449 
450 template <typename T>
451 void RBTree<T>::insert(RBTNode<T>* &tree, RBTNode<T>* node)
452 {
453     RBTNode<T>* parent = nullptr;    // 插入點的父節點
454     RBTNode<T>* root = tree;        // 輔助尋找parent
455 
456     while ( root != nullptr )        // 尋找插入點
457     {
458         parent = root;
459         if ( node->mKey < root->mKey )
460             root = root->mLeft;
461         else
462             root = root->mRight;
463     }
464 
465     node->mParent = parent;            // 設置node結點的父節點
466     if ( parent != nullptr )        // 有父節點則插入爲子結點
467         if ( node->mKey < parent->mKey )
468             parent->mLeft = node;
469         else
470             parent->mRight = node;
471     else                            // 父節點爲空則設爲根節點
472         tree = node;
473 
474     node->mColor = RED;                // 設爲紅色
475     ++mCount;
476 
477     insertFixUp(tree, node);        // 只有父節點是紅色才須要平衡,可是要注意根節點沒有父親且默認插入的是紅色
478 }
479 
480 template <typename T>
481 void RBTree<T>::insert(T key)
482 {
483     RBTNode<T>* node = new RBTNode<T>(RED, key, nullptr, nullptr, nullptr);    // 顏色在重載版本改成紅色,此處可任意填寫
484 
485     insert(mRoot, node);
486 }
487 
488 template <typename T>
489 void RBTree<T>::removeFixUp(RBTNode<T>* &tree, RBTNode<T>* del_child, RBTNode<T>* del_parent)    // 刪除修正紅黑樹(被刪除的是黑色)
490 {
491     RBTNode<T>* other;    // child的兄弟(原來的叔伯)
492 
493     // del_child爲假或del_child爲黑結點,且del_child不是根節點(del_child若是不是根節點就絕對是nullptr)
494     while ( (!del_child || del_child->mColor==BLACK) && del_child!=tree )    // B黑,R紅,p=parent,c=child,o=other,ol=other->left,or=other->right
495     {
496         if ( del_parent->mLeft == del_child )        // 若是del_child是左結點;注意替換者已經離開了,因此child和parent是父子關係
497         {                                            // 父親絕對有兩個兒子,由於del_child原先是黑色孫子,因此絕對有一個叔伯(如今是兄弟)
498             other = del_parent->mRight;
499             if ( other->mColor == RED )                                // del_child的兄弟是紅節點,它的子結點一定全是黑色
500             {
501                 other->mColor = BLACK;
502                 del_parent->mColor = RED;
503                 lRotate(tree, del_parent);
504                 other = del_parent->mRight;
505             }
506 
507             if ( (!other->mLeft || other->mLeft->mColor==BLACK) &&        // del_child兄弟的左結點爲假或者爲黑,且右結點也爲假或者爲黑
508                  (!other->mRight || other->mRight->mColor==BLACK) )    // 上面if保證del_child的兄弟也是黑色
509             {
510                 other->mColor = RED;
511                 del_child = del_parent;
512                 del_parent = del_child->mParent;
513             }
514             else
515             {
516                 if ( !other->mRight || other->mRight->mColor==BLACK )        // del_child兄弟是黑色,且該兄弟孩子不全爲黑
517                 {
518                     other->mLeft->mColor = BLACK;
519                     other->mColor = RED;
520                     rRotate(tree, other);
521                     other = del_parent->mRight;
522                 }
523 
524                 other->mColor = del_parent->mColor;
525                 del_parent->mColor = BLACK;
526                 other->mRight->mColor = BLACK;
527                 lRotate(tree, del_parent);
528                 del_child = tree;
529                 break;
530             }
531         }
532         else                                        // 若是del_child是右結點
533         {
534             other = del_parent->mLeft;
535             if ( other->mColor == RED )
536             {
537                 other->mColor = BLACK;
538                 del_parent->mColor = RED;
539                 rRotate(tree, del_parent);
540                 other = del_parent->mLeft;
541             }
542 
543             if ( (!other->mLeft || other->mLeft->mColor==BLACK) &&
544                  (!other->mRight || other->mRight->mColor==BLACK) )
545             {
546                 other->mColor = RED;
547                 del_child = del_parent;
548                 del_parent = del_child->mParent;
549             }
550             else
551             {
552                 if ( !other->mLeft || other->mLeft->mColor==BLACK )
553                 {
554                     other->mRight->mColor = BLACK;
555                     other->mColor = RED;
556                     lRotate(tree, other);
557                     other = del_parent->mLeft;
558                 }
559 
560                 other->mColor = del_parent->mColor;
561                 del_parent->mColor = BLACK;
562                 other->mLeft->mColor = BLACK;
563                 rRotate(tree, del_parent);
564                 del_child = tree;                    // 也能夠改爲 tree->color = BLACK;
565                 break;
566             }
567         }
568     }
569 
570     if ( del_child != nullptr )                    // del_child若是存在且是紅色,或者是根節點
571         del_child->mColor = BLACK;
572 }
573 
574 template <typename T>
575 void RBTree<T>::remove(RBTNode<T>* &tree, RBTNode<T>* del)
576 {
577     RBTNode<T> *child, *parent;
578     RBTColor color;
579 
580     if ( del->mLeft!=nullptr && del->mRight!=nullptr )        // 若是刪除結點有兩個孩子,須要找一個替換者
581     {
582         RBTNode<T>* replace = del->mRight;            // 替換者指向右結點最小者;也能夠指向左結點的最大者
583         while ( replace->mLeft != nullptr )
584             replace = replace->mLeft;
585 
586         if ( del->mParent != nullptr )                // 更新父結點指向替換者
587         {
588             if ( del->mParent->mLeft == del )
589                 del->mParent->mLeft = replace;
590             else
591                 del->mParent->mRight = replace;
592         }
593         else
594             tree = replace;
595 
596         child = replace->mRight;                        // 保存替換者的子結點、父結點、顏色
597         parent = replace->mParent;
598         color = replace->mColor;
599 
600         if ( del == parent )                        // 刪除的是替換者的父結點(這時替換者就是del的右結點,由於替換者沒有左結點,因此del的右結點最小)
601             parent = replace;
602         else
603         {
604             if ( child != nullptr )
605                 child->mParent = parent;
606             parent->mLeft = child;                    // 替換者的父親接管替換者的兒子(此時替換者只有右兒子,由於本身是右子樹的最左下者)
607 
608             replace->mRight = del->mRight;            // 更新替換者和被刪除者右兒子的關係(由於替換者位於右子樹)
609             del->mRight->mParent = replace;
610         }
611 
612         replace->mParent = del->mParent;                // 更新替換者的父親、顏色、以及與被刪除者左結點的關係
613         replace->mColor = del->mColor;
614         replace->mLeft = del->mLeft;
615         del->mLeft->mParent = replace;
616     }
617     else                                                    // 刪除結點孩子不足兩個,獨子或者葉節點就是替換者
618     {
619         if ( del->mLeft != nullptr )                    // 保存替換者的子結點、父結點、顏色
620             child = del->mLeft;
621         else
622             child = del->mRight;
623         parent = del->mParent;
624         color = del->mColor;
625 
626         if ( child != nullptr )                        // 更新 '被刪除結點的父節點' 和 '被刪除結點的子結點' 的關係
627             child->mParent = parent;                    // 父親(也就是被刪除結點)被刪除,因此爺爺直接和惟一一個孫子互相更新關係便可
628         if ( parent != nullptr )
629         {
630             if ( parent->mLeft == del )
631                 parent->mLeft = child;
632             else
633                 parent->mRight = child;
634         }
635         else
636             tree = child;
637     }
638 
639     --mCount;                                    // 結點計數減一
640 
641     if ( color == BLACK )                        // 若是替換者或被刪除者是黑色須要從新平衡(被刪除者有兩個兒子則是替換者),由於刪除了一個黑結點
642         removeFixUp(tree, child, parent);        // child若是不是根節點或紅色節點,那它絕對是nullptr指針(替換者至多有一個紅色兒子,且該兒子沒有後代)
643 
644     delete del;                                    // 刪除節點並返回
645     del = nullptr;
646 }
647 
648 template <typename T>
649 bool RBTree<T>::remove(T key)
650 {
651     bool ret = false;
652     RBTNode<T>* node = search(mRoot, key);
653 
654     if ( node != nullptr )
655     {
656         remove(mRoot, node);
657         ret = true;
658     }
659 
660     return ret;
661 }
662 
663 template <typename T>
664 void RBTree<T>::printTree(RBTNode<T> const* const tree, bool firstNode) const
665 {
666     if ( tree==nullptr )
667         return;
668 
669     bool static outTag[64] = {false};    // size = max layer limit;
670     uint8_t static layer = 0;
671     uint8_t i;
672     ++layer;
673 
674     if ( layer >= 2 )
675     {
676         for (i=2; i<layer; ++i )
677             if ( outTag[i] )
678                 cout << "|       ";
679             else
680                 cout << "        ";
681         cout << "+-------" << flush;
682     }
683     cout << tree->mKey << ' ' << (tree->mColor==BLACK ? 'B' : 'R') << endl;
684 
685     for ( i=2-1; i>0; --i)        // 從右往左輸出結點,即先打印最右邊結點,其次次右邊的結點;此循環不輸出最左邊的結點
686     {
687         if ( (tree->mLeft+i) != nullptr )    // 注意樹的子結點指針必須是從左往右依次排列,中間不能有其它變量(left_1,left_2,left_3...left_n)
688         {                                    // 若是你的子結點數量不定,必定要把後面的首個指針設爲nullptr
689             outTag[layer] = !firstNode;
690             printTree(tree->mRight, false);
691         }
692     }
693     if ( tree->mLeft != nullptr )            // 輸出最左邊的結點
694     {
695         printTree(tree->mLeft, true);
696         outTag[layer] = firstNode;
697     }
698 
699     --layer;
700 }
701 
702 template <typename T>
703 void RBTree<T>::printTree() const
704 {
705     printTree(mRoot, true);    // 右邊參數此時無心義
706 }
707 
708 template <typename T>
709 void RBTree<T>::destroy(RBTNode<T>* &tree)
710 {
711     if ( tree == nullptr )
712         return;
713 
714     if ( tree->mLeft != nullptr )
715         destroy(tree->mLeft);
716     if ( tree->mRight != nullptr )
717         destroy(tree->mRight);
718 
719     delete tree;
720 }
721 
722 template <typename T>
723 void RBTree<T>::destroy()
724 {
725     destroy(mRoot);
726 
727     mRoot = nullptr;
728     mCount = 0ull;
729     mHeight = 0;
730 }
731 
732 template <typename T>
733 uint64_t RBTree<T>::getCount() const
734 {
735     return mCount;
736 }
737 
738 template <typename T>
739 uint16_t RBTree<T>::updateHeight(RBTNode<T> *node)
740 {
741     if ( node == nullptr )
742         return 0;
743 
744     return max(updateHeight(node->mLeft), updateHeight(node->mRight))+1;
745 }
746 
747 template <typename T>
748 uint16_t RBTree<T>::getHeight(bool update)
749 {
750     if ( update == true )
751         mHeight = updateHeight(mRoot);
752 
753     return mHeight;
754 }
755 
756 template <typename T>
757 uint16_t RBTree<T>::max(uint16_t left, uint16_t right) const
758 {
759     return (left > right) ? left : right;
760 }
761 
762 template <typename T>
763 bool RBTree<T>::rootIsNullptr() const
764 {
765     return mRoot==nullptr;
766 }
767 
768 template <typename T>
769 T RBTree<T>::getRootKey() const
770 {
771     return (rootIsNullptr()) ? ~0ull : mRoot->mKey;
772 }
773 
774 }
775 
776 #endif // RBTREE_H

main.cpp

 

  1 #include "RBTree.h"
  2 
  3 #include "Times.h"
  4 
  5 using namespace std;
  6 using namespace Viclib;
  7 
  8 typedef uint64_t templateType;
  9 typedef uint64_t sizeType;
 10 
 11 static bool checkTree(RBTree<templateType>* tree);
 12 
 13 int main(int argc, char* argv[])
 14 {
 15     // msys2終端1920*2寬424個英文字符
 16     uint16_t layer = 16;
 17 
 18     if ( argc == 2 && atoi(argv[1])>=0 )
 19         layer = static_cast<uint16_t>(atoi(argv[1]));
 20     else {
 21         cout << "請輸入結點層數,注意內存大小" << endl;
 22         cin >> layer;
 23     }
 24 
 25     timingStart();
 26     cout << endl;
 27 
 28     uint64_t const count = (1ull<<layer)-1ull;
 29 
 30     cout << "您設定的最大層數上限:" << layer << endl;
 31     cout << "您設定的最大結點數上限:" << count << endl;
 32 
 33     templateType *t = nullptr, tmp = 0;
 34     RBTree<templateType>* tree = new RBTree<templateType>();
 35 
 36     cout << endl << "添加元素:\n\tkey\tcount\tlayer" << endl;
 37     srand(static_cast<uint32_t>(time(nullptr)));
 38     while ( tree->getCount() < count )
 39     {
 40         do
 41         {
 42             tmp = static_cast<templateType>(
 43                 static_cast<sizeType>(rand())
 44                 * static_cast<sizeType>(rand())
 45                 * static_cast<sizeType>(rand())
 46                 % (count*2));
 47         } while(tree->iterativeSearch(tmp));
 48         //tmp = setArr(count);
 49         tree->insert(tmp);
 50         //cout << "插入:\t" << tmp << "\t" << tree->getCount() << "\t" << tree->getHeight(true) << endl;
 51         
 52         if ( (tree->getCount()*100%count) == 0 || tree->getCount() == count )
 53             cout << "\r已添加:" << setw(2) << tree->getCount()*100.0/count << '%' << flush;
 54     }
 55     cout << endl;
 56 
 57     cout << "\n紅黑樹平衡校驗結果:";
 58     if ( checkTree(tree) )
 59         cout << "成功\n" << endl;
 60     else
 61     {
 62         cout << "節點的路徑與左邊第一個節點路徑黑色數量不一樣\n" << endl;
 63 
 64         cout << "輸出目錄樹模式關係圖:" << endl;
 65         tree->printTree();
 66         cout << endl;
 67 
 68         exit(1);
 69     }
 70 
 71     cout << "前序遍歷: ";
 72     tree->preOrder();
 73     cout << "\n中序遍歷: ";
 74     tree->inOrder();
 75     cout << "\n後序遍歷: ";
 76     tree->postOrder();
 77     cout << "\n廣度優先: ";
 78     tree->levelOrder();
 79     cout << endl;
 80 
 81     if ( (tree!=nullptr) && ((t = const_cast<templateType*>(tree->minimum())) != nullptr) )
 82         cout << "最小結點:" << *t << endl;
 83     if ( (tree!=nullptr) && ((t = const_cast<templateType*>(tree->maximum())) != nullptr) )
 84         cout << "最大結點:" << *t << endl;
 85     cout << "樹的結點數:" << tree->getCount() << endl;
 86     cout << "樹的高度(不含最底層葉節點):" << tree->getHeight(true) << endl;
 87 
 88 //    cout << "輸出樹形關係圖:" << endl;
 89 //    tree->printGraph();
 90 //    cout << endl;
 91 
 92     cout << "輸出目錄樹模式關係圖:" << endl;
 93     tree->printTree();
 94     cout << endl;
 95 
 96     cout << "開始刪除:\n\tkey\tcount\tlayer" << endl;
 97     srand(static_cast<uint32_t>(time(nullptr)));
 98     while ( !tree->rootIsNullptr() )        // 隨機數刪除
 99     {
100         do
101         {
102             tmp = static_cast<templateType>(
103                 static_cast<sizeType>(rand())
104                 * static_cast<sizeType>(rand())
105                 * static_cast<sizeType>(rand())
106                 % (count*2));
107         } while(!tree->iterativeSearch(tmp));
108         if ( tree->remove(tree->getRootKey()) )
109         {
110             //cout << "刪除:\t" << tmp << "\t" << tree->getCount() << "\t" << tree->getHeight(true) << endl;
111 
112             if ( (tree->getCount()*100%count) == 0 || tree->getCount() == count )
113                 cout << "\r已刪除:" << setw(2) << (count-tree->getCount())*100.0/count << '%' << flush;
114         }
115     }
116     cout << endl;
117 
118     tree->destroy();
119     tree = nullptr;
120 
121     cout << endl;
122     timingEnd();
123 
124     return 0;
125 }
126 
127 static bool checkTree(RBTree<templateType>* tree)
128 {
129     if ( tree == nullptr )
130         return true;
131 
132     queue<RBTNode<templateType>*> tmp;
133     tmp.push(tree->search(tree->getRootKey()));
134     queue<RBTNode<templateType>*> leaf;
135     RBTNode<templateType>* t;
136     uint8_t i = 0;
137     uint8_t j = 0;
138 
139     while( tmp.size() > 0 )
140     {
141         t = tmp.front();
142 
143         if ( t->mLeft != nullptr )
144             tmp.push(t->mLeft);
145         else
146             leaf.push(t);
147 
148         if ( t->mRight != nullptr )
149             tmp.push(t->mRight);
150         else
151             leaf.push(t);
152 
153         tmp.pop();
154     }
155 
156     t = leaf.front();
157     leaf.pop();
158     while ( t != nullptr )
159     {
160         if ( t->mColor == BLACK ) ++i;
161         t = t->mParent;
162     }
163 
164     while ( !leaf.empty() )
165     {
166         t = leaf.front();
167 
168         j = 0;
169         if ( t->mColor == BLACK ) ++j;
170         while ( t->mParent != nullptr )
171         {
172             t = t->mParent;
173             if ( t->mColor == BLACK ) ++j;
174         }
175 
176         if ( i != j )
177         {
178             cout << leaf.front()->mKey;
179             return false;
180         }
181 
182         leaf.pop();
183     }
184 
185     return true;
186 }
相關文章
相關標籤/搜索