二叉树之红黑树(RBTree)

  详解以后再补充。。。

红黑树和AVL树6层模式下的最少结点数

  通过图可以看到红黑树可以实现更少的结点,反过来说就是同样的结点数红黑树最大数高会超过AVL树

  https://www.cs.usfca.edu/~galles/visualization/Algorithms.html这个网站可以测试动态效果,下图就是截图于此

红黑树插入删除步骤

输出

代码

其余代码:https://github.com/Duacai/Data-Structure-and-Algorithms/tree/master/BSTree

工程通过Qt Creator创建

RBTree.h

  1 #ifndef RBTREE_H
  2 #define RBTREE_H
  3
  4 #include <iostream>
  5 #include <iomanip>
  6 #include <queue>
  7
  8 #include "Exception.h"
  9
 10 using namespace std;
 11
 12 namespace LinWeiJie_lib
 13 {
 14
 15 enum RBTColor { RED, BLACK };
 16
 17 template <typename T>
 18 class RBTNode
 19 {
 20 public:
 21     RBTColor mColor;
 22     T mKey;
 23     RBTNode<T>* mLeft;
 24     RBTNode<T>* mRight;
 25     RBTNode<T>* mParent;
 26
 27     RBTNode(RBTColor color, T key, RBTNode<T>* left, RBTNode<T>* right, RBTNode<T>* parent) :
 28         mColor(color), mKey(key), mLeft(left), mRight(right), mParent(parent) {}
 29 };
 30
 31 template <typename T>
 32 class RBTree
 33 {
 34 private:
 35     RBTNode<T>* mRoot;
 36     uint64_t mCount;
 37     uint16_t mHeight;
 38     uint8_t mKeyStrLen;
 39
 40     void preOrder(RBTNode<T>* tree) const;
 41     void inOrder(RBTNode<T>* tree) const;
 42     void postOrder(RBTNode<T>* tree) const;
 43
 44     void levelOrder(RBTNode<T>* tree) const;
 45
 46     RBTNode<T>* search(RBTNode<T>* tree, T key) const;
 47     RBTNode<T>* iterativeSearch(RBTNode<T>* tree, T key) const;
 48
 49     RBTNode<T>* minimum(RBTNode<T>* tree) const;
 50     RBTNode<T>* maximum(RBTNode<T>* tree) const;
 51
 52     void lRotate(RBTNode<T>* &tree, RBTNode<T>* node) const;
 53     void rRotate(RBTNode<T>* &tree, RBTNode<T>* node) const;
 54
 55     void insert(RBTNode<T>* &tree, RBTNode<T>* node);
 56     void insertFixUp(RBTNode<T>* &tree, RBTNode<T>* node);    // 插入修正红黑树
 57
 58     void remove(RBTNode<T>* &tree, RBTNode<T> *del);
 59     void removeFixUp(RBTNode<T>* &tree, RBTNode<T>* del, RBTNode<T>* parent);    // 删除修正红黑树(被删除的是黑色)
 60
 61     void print(RBTNode<T> const* const tree, T key, int direction) const;
 62     void printGraph(RBTNode<T> const* const tree) const;
 63     void printTree(RBTNode<T> const* const tree, bool firstNode) const;
 64
 65     void destroy(RBTNode<T>* &tree);
 66     uint16_t max(uint16_t left, uint16_t right) const;
 67     uint16_t updateHeight(RBTNode<T> *node);
 68
 69 public:
 70     RBTree();
 71     ~RBTree();
 72
 73     void preOrder() const;
 74     void inOrder() const;
 75     void postOrder() const;
 76
 77     void levelOrder() const;
 78
 79     RBTNode<T>* search(T key) const;
 80     RBTNode<T>* iterativeSearch(T key) const;
 81
 82     T const* minimum() const;
 83     T const* maximum() const;
 84
 85     RBTNode<T>* successor(RBTNode<T>* node) const;
 86     RBTNode<T>* predecessor(RBTNode<T>* node) const;
 87
 88     void insert(T key);
 89     bool remove(T key);
 90
 91     void print() const;
 92     void printGraph();            // 需要更新高度
 93     void printTree() const;
 94
 95     void destroy();
 96     uint64_t getCount() const;
 97     uint16_t getHeight(bool update = true);
 98     bool rootIsNullptr() const;
 99     T getRootKey() const;
100     uint8_t setKeyStrLen();
101 };
102
103 template <typename T>
104 RBTree<T>::RBTree() : mRoot(nullptr), mCount(0ull), mHeight(0), mKeyStrLen(0)
105 {
106
107 }
108
109 template <typename T>
110 RBTree<T>::~RBTree()
111 {
112     destroy();
113 }
114
115 template <typename T>
116 void RBTree<T>::preOrder(RBTNode<T>* tree) const
117 {
118     if ( tree != nullptr )
119     {
120         cout << tree->mKey << " " << flush;
121         preOrder(tree->mLeft);
122         preOrder(tree->mRight);
123     }
124 }
125
126 template <typename T>
127 void RBTree<T>::preOrder() const
128 {
129     preOrder(mRoot);
130     cout << endl;
131 }
132
133 template <typename T>
134 void RBTree<T>::inOrder(RBTNode<T>* tree) const
135 {
136     if ( tree != nullptr )
137     {
138         inOrder(tree->mLeft);
139         cout << tree->mKey << " " << flush;
140         inOrder(tree->mRight);
141     }
142 }
143
144 template <typename T>
145 void RBTree<T>::inOrder() const
146 {
147     inOrder(mRoot);
148     cout << endl;
149 }
150
151 template <typename T>
152 void RBTree<T>::postOrder(RBTNode<T>* tree) const
153 {
154     if ( tree != nullptr )
155     {
156         postOrder(tree->mLeft);
157         postOrder(tree->mRight);
158         cout << tree->mKey << " " << flush;
159     }
160 }
161
162 template <typename T>
163 void RBTree<T>::postOrder() const
164 {
165     postOrder(mRoot);
166     cout << endl;
167 }
168
169 template <typename T>
170 void RBTree<T>::levelOrder(RBTNode<T>* tree) const
171 {
172     if ( tree != nullptr )
173     {
174         queue<RBTNode<T>*> tmp;
175         tmp.push(tree);
176
177         while( tmp.size() > 0 )
178         {
179             RBTNode<T>* t = tmp.front();
180
181             if ( t->mLeft != nullptr )
182                 tmp.push(t->mLeft);
183
184             if ( t->mRight != nullptr )
185                 tmp.push(t->mRight);
186
187             tmp.pop();
188
189             cout << t->mKey << " " << flush;
190         }
191     }
192 }
193
194 template <typename T>
195 void RBTree<T>::levelOrder() const
196 {
197     levelOrder(mRoot);
198     cout << endl;
199 }
200
201 template <typename T>
202 RBTNode<T>* RBTree<T>::search(RBTNode<T>* tree, T key) const
203 {
204     if ( tree==nullptr || key==tree->mKey )
205         return tree;
206
207     if ( key < tree->mKey )
208         return search(tree->mLeft, key);
209     else
210         return search(tree->mRight, key);
211 }
212
213 template <typename T>
214 RBTNode<T>* RBTree<T>::search(T key) const
215 {
216     return search(mRoot, key);
217 }
218
219 template <typename T>
220 RBTNode<T>* RBTree<T>::iterativeSearch(RBTNode<T>* tree, T key) const
221 {
222     while ( tree!=nullptr && key!=tree->mKey )
223     {
224         if ( key < tree->mKey )
225             tree = tree->mLeft;
226         else
227             tree = tree->mRight;
228     }
229
230     return tree;
231 }
232
233 template <typename T>
234 RBTNode<T>* RBTree<T>::iterativeSearch(T key) const
235 {
236     return iterativeSearch(mRoot, key);
237 }
238
239 template <typename T>
240 RBTNode<T>* RBTree<T>::minimum(RBTNode<T>* tree) const
241 {
242     if ( tree == nullptr )
243         return nullptr;
244
245     while ( tree->mLeft != nullptr )
246         tree = tree->mLeft;
247
248     return tree;
249 }
250
251 template <typename T>
252 T const* RBTree<T>::minimum() const
253 {
254     RBTNode<T>* ret = minimum(mRoot);
255     if ( ret != nullptr )
256         return &ret->mKey;
257
258     return nullptr;
259 }
260
261 template <typename T>
262 RBTNode<T>* RBTree<T>::maximum(RBTNode<T>* tree) const
263 {
264     if ( tree == nullptr )
265         return nullptr;
266
267     while ( tree->mRight != nullptr )
268         tree = tree->mRight;
269
270     return tree;
271 }
272
273 template <typename T>
274 T const* RBTree<T>::maximum() const
275 {
276     RBTNode<T>* ret = maximum(mRoot);
277     if ( ret != nullptr )
278         return &ret->mKey;
279
280     return nullptr;
281 }
282
283 template <typename T>
284 RBTNode<T>* RBTree<T>::successor(RBTNode<T>* tree) const    // 查找tree的后继,比tree大
285 {
286     if ( tree->right != nullptr )            // 在右节点查找最小结点
287         return minimum(tree->right);
288
289     RBTNode<T>* p = tree->parent;
290     while ( p!=nullptr && tree==p->right )    // 父节点非空且自己是右节点就继续寻找,直至自己是左结点或父节点为空
291     {
292         tree = p;
293         p = p->parent;
294     }
295
296     return p;
297 }
298
299 template <typename T>
300 RBTNode<T>* RBTree<T>::predecessor(RBTNode<T>* tree) const    // 查找tree的前任,比tree小
301 {
302     if ( tree->left != nullptr )            // 在左结点查找最大结点
303         return maximum(tree->left);
304
305     RBTNode<T>* p = tree->parent;
306     while ( p!=nullptr && tree==p->left )    // 父节点非空且自己是左结点就继续寻找,直至自己是右节点或父节点为空
307     {
308         tree = p;
309         p = p->parent;
310     }
311
312     return p;
313 }
314
315 /*    左旋
316  *    p                     p
317  *    |                     |
318  *   old                   new
319  *   / \     --(左旋)-->    / 320  *  a  new                old c
321  *     / \                / 322  *    B   c              a   B
323  */
324 template <typename T>
325 void RBTree<T>::lRotate(RBTNode<T>* &tree, RBTNode<T>* node) const    // 将右边重的结点旋转至左边重
326 {                                                                    // 当前结点成为右孩子的左孩子,右孩子的左孩子成为自己的右孩子,右孩子则替换自己位置
327     RBTNode<T>* r = node->mRight;            // 新结点指向右节点
328
329     node->mRight = r->mLeft;                    // 更新 【当前结点(旧结点)】 与 【右节点(新结点)的左孩子】 之间的关系
330     if ( r->mLeft != nullptr )
331         r->mLeft->mParent = node;
332
333     r->mParent = node->mParent;                // 更新 父节点 和 新孩子 之间的关系
334     if ( node->mParent == nullptr )
335         tree = r;
336     else
337     {
338         if ( node == node->mParent->mLeft )        // 判断并更新父节点的新孩子
339             node->mParent->mLeft = r;
340         else
341             node->mParent->mRight = r;
342     }
343
344     r->mLeft = node;                            // 更新 新旧结点 之间的关系
345     node->mParent = r;
346 }
347
348 /*    右旋
349  *      p                  p
350  *      |                  |
351  *     old                new
352  *     / \   --(右旋)-->   / 353  *   new  c              a  old
354  *   / \                    / 355  *  a   B                  B   c
356  */
357 template <typename T>
358 void RBTree<T>::rRotate(RBTNode<T>* &tree, RBTNode<T>* node) const
359 {
360     RBTNode<T>* l = node->mLeft;
361
362     node->mLeft = l->mRight;
363     if ( l->mRight != nullptr )
364         l->mRight->mParent = node;
365
366     l->mParent = node->mParent;
367     if ( node->mParent == nullptr )
368         tree = l;
369     else
370     {
371         if ( node == node->mParent->mLeft )
372             node->mParent->mLeft = l;
373         else
374             node->mParent->mRight = l;
375     }
376
377     l->mRight = node;
378     node->mParent = l;
379 }
380
381 template <typename T>
382 void RBTree<T>::insertFixUp(RBTNode<T>* &tree, RBTNode<T>* node)    // 插入修正红黑树
383 {
384     RBTNode<T> *parent, *gparent;    // 父结点,爷爷结点
385
386     // node有父结点且父亲是红色(R红色、B黑色、@插入结点)
387     while ( (parent = node->mParent) && (parent->mColor==RED) )
388     {
389         gparent = parent->mParent;
390
391         if ( parent == gparent->mLeft )    // 父亲是左孩子,叔叔是右孩子
392         {
393             {    // 叔叔有效且是红色,while保证父亲也是红色
394                 RBTNode<T>* uncle = gparent->mRight;
395                 if ( uncle && uncle->mColor==RED )    // 父亲是红色,自己默认又是红色,所以需要变色
396                 {                                    // 将父亲和叔叔设为黑结点,爷爷设为红节点;
397                     uncle->mColor = BLACK;    //   B              R
398                     parent->mColor = BLACK;    // R   R        B   B
399                     gparent->mColor = RED;    // R(@)            R(@)    // 不区分自己是左孩子还是右孩子
400                     node = gparent;                    // node指向爷爷后向上再判断其它结点是否需要平衡
401                     continue;
402                 }
403             }
404             // 父亲为红色时如果叔叔不是红色,则叔叔必是黑色叶子,且父亲的子女也全是叶子;因为父亲必须有一个叶子子结点才能插入,如果叔叔不是叶子或父亲的儿子不全是叶子则无法平衡
405             {    // 叔叔为空,自己是红色父亲的右孩子,旋转成左孩子(父子身份也交换,且父子仍为红色)
406                 if ( parent->mRight == node )// 红节点的子结点如有叶子则全是叶子,否则不平衡;父亲之前没有子结点则父亲无兄弟
407                 {
408                     RBTNode<T>* tmp;
409                     lRotate(tree, parent);    // 左旋后node替换父亲,父亲则成为自己的左孩子,变成左左模式,左左都是红色
410                     tmp = parent;            // 旋转后修正父子指针位置,父子互换
411                     parent = node;            //     B        B          B
412                     node = tmp;                //    R        R(@)       R
413                 }                            //     R(@)    R          R(@)
414             }
415
416             {    // 叔叔为空,自己是红色父亲的左孩子
417                 parent->mColor = BLACK;        //     B        R          B
418                 gparent->mColor = RED;        //    R        B        R(@)   R
419                 rRotate(tree, gparent);        // R(@)        R(@)
420             }
421         }
422         else                        // 父亲是右孩子,伯父是左孩子
423         {
424             {    // 伯父有效且是红色,while保证父亲也是红色
425                 RBTNode<T>* uncle = gparent->mLeft;
426                 if ( uncle && uncle->mColor==RED )
427                 {
428                     uncle->mColor = BLACK;    //     B            R
429                     parent->mColor = BLACK;    // R   R         B   B
430                     gparent->mColor = RED;    //       R(@)            R(@)
431                     node = gparent;
432                     continue;
433                 }
434             }
435
436             {    // 伯父为空或为黑色,自己是红色父亲的左孩子,旋转成右孩子(父子身份也交换,且父子仍为红色)
437                 if ( parent->mLeft == node )
438                 {
439                     RBTNode<T>* tmp;
440                     rRotate(tree, parent);
441                     tmp = parent;            // B         B       B
442                     parent = node;            //  R        R(@)     R
443                     node = tmp;                // R(@)          R       R(@)
444                 }
445             }
446
447             {    // 伯父为空或为黑色,自己是红色父亲的右孩子
448                 parent->mColor = BLACK;        // B         R            B
449                 gparent->mColor = RED;        //    R        #       R       R(@)
450                 lRotate(tree, gparent);        //     R(@)      R(@)
451             }
452         }
453     }
454
455     tree->mColor = BLACK;    // 如果没有父节点则当前结点就是根节点;父节点为黑则这条语句无意义
456 }
457
458 template <typename T>
459 void RBTree<T>::insert(RBTNode<T>* &tree, RBTNode<T>* node)
460 {
461     RBTNode<T>* parent = nullptr;    // 插入点的父节点
462     RBTNode<T>* root = tree;        // 辅助寻找parent
463
464     while ( root != nullptr )        // 寻找插入点
465     {
466         parent = root;
467         if ( node->mKey < root->mKey )
468             root = root->mLeft;
469         else
470             root = root->mRight;
471     }
472
473     node->mParent = parent;            // 设置node结点的父节点
474     if ( parent != nullptr )        // 有父节点则插入为子结点
475         if ( node->mKey < parent->mKey )
476             parent->mLeft = node;
477         else
478             parent->mRight = node;
479     else                            // 父节点为空则设为根节点
480         tree = node;
481
482     node->mColor = RED;                // 设为红色
483     ++mCount;
484
485     insertFixUp(tree, node);        // 只有父节点是红色才需要平衡,但是要注意根节点没有父亲且默认插入的是红色
486 }
487
488 template <typename T>
489 void RBTree<T>::insert(T key)
490 {
491     RBTNode<T>* node = new RBTNode<T>(RED, key, nullptr, nullptr, nullptr);    // 颜色在重载版本改为红色,此处可任意填写
492
493     insert(mRoot, node);
494 }
495
496 template <typename T>
497 void RBTree<T>::removeFixUp(RBTNode<T>* &tree, RBTNode<T>* del_child, RBTNode<T>* del_parent)    // 删除修正红黑树(被删除的是黑色)
498 {
499     RBTNode<T>* other;    // child的兄弟(原来的叔伯)
500
501     // del_child为假或del_child为黑结点,且del_child不是根节点(del_child如果不是根节点就绝对是nullptr)
502     while ( (!del_child || del_child->mColor==BLACK) && del_child!=tree )    // B黑,R红,p=parent,c=child,o=other,ol=other->left,or=other->right
503     {
504         if ( del_parent->mLeft == del_child )        // 如果del_child是左结点;注意替换者已经离开了,所以child和parent是父子关系
505         {                                            // 父亲绝对有两个儿子,因为del_child原先是黑色孙子,所以绝对有一个叔伯(现在是兄弟)
506             other = del_parent->mRight;
507             if ( other->mColor == RED )                                // del_child的兄弟是红节点,它的子结点必定全是黑色
508             {
509                 other->mColor = BLACK;                //        B(p)                   B(o)                B
510                 del_parent->mColor = RED;            //    B(c)    R(o)           R(p)    B           R(p)    B
511                 lRotate(tree, del_parent);            //    B   B   B   B         B(c)B   B   B         B(c)B(o)B   B
512                 other = del_parent->mRight;            //         B B B B        B B B B                B B B B
513             }
514
515             if ( (!other->mLeft || other->mLeft->mColor==BLACK) &&        // del_child兄弟的左结点为假或者为黑,且右结点也为假或者为黑
516                  (!other->mRight || other->mRight->mColor==BLACK) )    // 上面if保证del_child的兄弟也是黑色
517             {                                        //         B                   B(p)
518                 other->mColor = RED;                    //       R(p)    B           R(c)    B
519                 del_child = del_parent;                //     B(c)B(o)B   B         B   R(o)B   B
520                 del_parent = del_child->mParent;        //    B B B B                B B B B
521             }
522             else
523             {
524                 if ( !other->mRight || other->mRight->mColor==BLACK )        // del_child兄弟是黑色,且该兄弟孩子不全为黑
525                 {                                    //           B                   B
526                     other->mLeft->mColor = BLACK;        //       R(p)    B           R(p)    B
527                     other->mColor = RED;                //   B(c)B(o)B   B         B(c)B   B   B
528                     rRotate(tree, other);            //    B B B B                B B   R(o)
529                     other = del_parent->mRight;        //                               B
530                 }
531
532                 other->mColor = del_parent->mColor;                        // del_child兄弟是黑色,且该兄弟右孩子是红色
533                 del_parent->mColor = BLACK;            //           B                    B
534                 other->mRight->mColor = BLACK;        //       R(p)    B            B       B
535                 lRotate(tree, del_parent);            //     B(c)B   B   B          B(p)B(o)B   B
536                 del_child = tree;                    //    B B   R(o)             B(c)  B
537                 break;                                //           B            B B
538             }
539         }
540         else                                        // 如果del_child是右结点
541         {
542             other = del_parent->mLeft;
543             if ( other->mColor == RED )
544             {
545                 other->mColor = BLACK;
546                 del_parent->mColor = RED;
547                 rRotate(tree, del_parent);
548                 other = del_parent->mLeft;
549             }
550
551             if ( (!other->mLeft || other->mLeft->mColor==BLACK) &&
552                  (!other->mRight || other->mRight->mColor==BLACK) )    //         B(p)
553             {                                        //       R(p)                R(c)(函数末尾设为B)
554                 other->mColor = RED;                    //   B(o)    B(c)        R(o)    B
555                 del_child = del_parent;                // B   B       R       B   B       R 1.2,完毕
556                 del_parent = del_child->mParent;        //    R                   R
557             }
558             else
559             {
560                 if ( !other->mLeft || other->mLeft->mColor==BLACK )
561                 {
562                     other->mRight->mColor = BLACK;    //
563                     other->mColor = RED;                //
564                     lRotate(tree, other);            //
565                     other = del_parent->mLeft;        //
566                 }
567
568                 other->mColor = del_parent->mColor;    //    B(p)         B(p)        B(o)
569                 del_parent->mColor = BLACK;            //  B(o)B(d)     B(o)B(d)    B   B(p) 2.1
570                 other->mLeft->mColor = BLACK;            // R     c      B     c            B(d)
571                 rRotate(tree, del_parent);
572                 del_child = tree;                    // 也可以改成 tree->color = BLACK;
573                 break;
574             }
575         }
576     }
577
578     if ( del_child != nullptr )                    // del_child如果存在且是红色,或者是根节点
579         del_child->mColor = BLACK;
580 }
581
582 template <typename T>
583 void RBTree<T>::remove(RBTNode<T>* &tree, RBTNode<T>* del)
584 {
585     RBTNode<T> *child, *parent;
586     RBTColor color;
587
588     if ( del->mLeft!=nullptr && del->mRight!=nullptr )        // 如果删除结点有两个孩子,需要找一个替换者
589     {
590         RBTNode<T>* replace = del->mRight;            // 替换者指向右结点最小者;也可以指向左结点的最大者
591         while ( replace->mLeft != nullptr )
592             replace = replace->mLeft;
593
594         if ( del->mParent != nullptr )                // 更新父结点指向替换者
595         {
596             if ( del->mParent->mLeft == del )
597                 del->mParent->mLeft = replace;
598             else
599                 del->mParent->mRight = replace;
600         }
601         else
602             tree = replace;
603
604         child = replace->mRight;                        // 保存替换者的子结点、父结点、颜色
605         parent = replace->mParent;
606         color = replace->mColor;
607
608         if ( del == parent )                        // 删除的是替换者的父结点(这时替换者就是del的右结点,因为替换者没有左结点,所以del的右结点最小)
609             parent = replace;
610         else
611         {
612             if ( child != nullptr )
613                 child->mParent = parent;
614             parent->mLeft = child;                    // 替换者的父亲接管替换者的儿子(此时替换者只有右儿子,因为自己是右子树的最左下者)
615
616             replace->mRight = del->mRight;            // 更新替换者和被删除者右儿子的关系(因为替换者位于右子树)
617             del->mRight->mParent = replace;
618         }
619
620         replace->mParent = del->mParent;                // 更新替换者的父亲、颜色、以及与被删除者左结点的关系
621         replace->mColor = del->mColor;
622         replace->mLeft = del->mLeft;
623         del->mLeft->mParent = replace;
624     }
625     else                                                    // 删除结点孩子不足两个,独子或者叶节点就是替换者
626     {
627         if ( del->mLeft != nullptr )                    // 保存替换者的子结点、父结点、颜色
628             child = del->mLeft;
629         else
630             child = del->mRight;
631         parent = del->mParent;
632         color = del->mColor;
633
634         if ( child != nullptr )                        // 更新 ‘被删除结点的父节点‘ 和 ‘被删除结点的子结点‘ 的关系
635             child->mParent = parent;                    // 父亲(也就是被删除结点)被删除,所以爷爷直接和唯一一个孙子互相更新关系即可
636         if ( parent != nullptr )
637         {
638             if ( parent->mLeft == del )
639                 parent->mLeft = child;
640             else
641                 parent->mRight = child;
642         }
643         else
644             tree = child;
645     }
646
647     --mCount;                                    // 结点计数减一
648
649     if ( color == BLACK )                        // 如果替换者或被删除者是黑色需要重新平衡(被删除者有两个儿子则是替换者),因为删除了一个黑结点
650         removeFixUp(tree, child, parent);        // child如果不是根节点或红色节点,那它绝对是nullptr指针(替换者至多有一个红色儿子,且该儿子没有后代)
651
652     delete del;                                    // 删除节点并返回
653     del = nullptr;
654 }
655
656 template <typename T>
657 bool RBTree<T>::remove(T key)
658 {
659     bool ret = false;
660     RBTNode<T>* node = search(mRoot, key);
661
662     if ( node != nullptr )
663     {
664         remove(mRoot, node);
665         ret = true;
666     }
667
668     return ret;
669 }
670
671 template <typename T>
672 void RBTree<T>::print(RBTNode<T> const* const tree, T key, int direction) const
673 {
674     if ( tree != nullptr )
675     {
676         if ( direction == 0 )
677             cout << setw(mKeyStrLen) << setfill(‘ ‘) << tree->mKey << "B is root" << endl;
678         else
679             cout << setw(mKeyStrLen) << tree->mKey << (tree->mColor==RED ? "R" : "B")
680                  << " is " << setw(mKeyStrLen) << key << "‘s "
681                  << setw(11) << (direction==(-1) ? "left child" : "right child") << endl;
682
683         print(tree->mLeft, tree->mKey, -1);
684         print(tree->mRight, tree->mKey, 1);
685     }
686 }
687
688 template <typename T>
689 void RBTree<T>::print() const
690 {
691     if ( mRoot != nullptr )
692         print(mRoot, mRoot->mKey, 0);
693 }
694
695 template <typename T>
696 void RBTree<T>::printGraph(RBTNode<T> const* const tree) const
697 {
698     uint16_t layer = 1;                    // 当前层,root为第一层
699     uint16_t height = mHeight;            // 树高,原树高不含叶子
700     uint64_t i, index;                    // i: 循环变量;index: 当前层最大结点数
701     char keyFill = ‘0‘;
702     queue<RBTNode<T> const *> q;        // 记录每层的所有节点,包括nullptr
703     q.push(tree);
704     while ( height > 0 )
705     {
706         cout << setw(2) << setfill(‘ ‘) << layer << " " << flush;        // 输出当前层号和当前层满节点数
707         RBTNode<T> const* tmp = nullptr;                                // 取出结点变量
708         index = 1ull<<(layer-1);
709         while ( index-- )
710         {
711             tmp = q.front();                                            // 取出结点
712             q.pop();
713             for ( i=0; i<((1ull<<(height-layer))-1ull)*(mKeyStrLen+1); ++i )    // 结点前的填充,+1 <<-->> "#"或者"*"占宽
714                 cout << " ";
715
716             if ( tmp != nullptr )                                        // 打印有效结点
717             {
718                 cout << right << setw(mKeyStrLen) << setfill(keyFill);
719                 if ( mKeyStrLen != 0 )
720                     cout << tmp->mKey;
721                 if ( tmp->mColor == BLACK )
722                     cout << "B";
723                 else
724                     cout << "R";
725
726                 if ( tmp->mLeft != nullptr )        // 加入左结点
727                     q.push(tmp->mLeft);
728                 else
729                     q.push(nullptr);
730
731                 if ( tmp->mRight != nullptr )    // 加入右节点
732                     q.push(tmp->mRight);
733                 else
734                     q.push(nullptr);
735             }
736             else                                                        // 打印无效结点
737             {
738                 cout << right << setw(mKeyStrLen+1) << setfill(‘@‘) << "@";    // +1 <<-->> "#"或者"*"占宽
739
740                 q.push(nullptr);                // 如果结点是空的则为其加入两个空子结点
741                 q.push(nullptr);
742             }
743
744             for ( i=0; i<((1ull<<(height-layer))-1ull)*(mKeyStrLen+1); ++i )    // 结点后的填充,+1 <<-->> "#"或者"*"占宽
745                 cout << " ";
746
747             if ( index != 0 )
748                 cout << right << setw(mKeyStrLen+1) << setfill(‘ ‘) << " ";    // 两节点间填充,因为父节点位于两节点的中间上面,而不是其中一个的上面,+1 <<-->> "#"或者"*"占宽
749
750             cout << flush;
751         }
752         cout << setw(3) << setfill(‘ ‘) << layer << endl;            // 输出一层换行
753
754         if ( ++layer > height )    // while循环出口,当前层大于总高度时退出
755             break;
756     }
757 }
758
759 template <typename T>
760 void RBTree<T>::printGraph()
761 {
762     if ( mRoot == nullptr )
763         return;
764
765     getHeight(true);
766     printGraph(mRoot);
767 }
768
769 template <typename T>
770 void RBTree<T>::printTree(RBTNode<T> const* const tree, bool firstNode) const
771 {
772     if ( tree==nullptr )
773         return;
774
775     bool static outTag[64] = {false};    // size = max layer limit;
776     uint8_t static layer = 0;
777     uint8_t i;
778     ++layer;
779
780     if ( layer >= 2 )
781     {
782         for (i=2; i<layer; ++i )
783             if ( outTag[i] )
784                 cout << "|       ";
785             else
786                 cout << "        ";
787         cout << "+-------" << flush;
788     }
789     cout << setw(mKeyStrLen) << tree->mKey << (tree->mColor==BLACK ? ‘B‘ : ‘R‘) << endl;
790
791     for ( i=2-1; i>0; --i)        // 从右往左输出结点,即先打印最右边结点,其次次右边的结点;此循环不输出最左边的结点
792     {
793         if ( (tree->mLeft+i) != nullptr )    // 注意树的子结点指针必须是从左往右依次排列,中间不能有其它变量(left_1,left_2,left_3...left_n)
794         {                                    // 如果你的子结点数量不定,一定要把后面的首个指针设为nullptr
795             outTag[layer] = !firstNode;
796             printTree(tree->mRight, false);
797         }
798     }
799     if ( tree->mLeft != nullptr )            // 输出最左边的结点
800     {
801         printTree(tree->mLeft, true);
802         outTag[layer] = firstNode;
803     }
804
805     --layer;
806 }
807
808 template <typename T>
809 void RBTree<T>::printTree() const
810 {
811     printTree(mRoot, true);    // 右边参数此时无意义
812 }
813
814 template <typename T>
815 void RBTree<T>::destroy(RBTNode<T>* &tree)
816 {
817     if ( tree == nullptr )
818         return;
819
820     if ( tree->mLeft != nullptr )
821         destroy(tree->mLeft);
822     if ( tree->mRight != nullptr )
823         destroy(tree->mRight);
824
825     delete tree;
826 }
827
828 template <typename T>
829 void RBTree<T>::destroy()
830 {
831     destroy(mRoot);
832
833     mRoot = nullptr;
834     mCount = 0ull;
835     mHeight = 0;
836     mKeyStrLen = 0;
837 }
838
839 template <typename T>
840 uint64_t RBTree<T>::getCount() const
841 {
842     return mCount;
843 }
844
845 template <typename T>
846 uint16_t RBTree<T>::updateHeight(RBTNode<T> *node)
847 {
848     if ( node == nullptr )
849         return 0;
850
851     return max(updateHeight(node->mLeft), updateHeight(node->mRight))+1;
852 }
853
854 template <typename T>
855 uint16_t RBTree<T>::getHeight(bool update)
856 {
857     if ( update == true )
858         mHeight = updateHeight(mRoot);
859
860     return mHeight;
861 }
862
863 template <typename T>
864 uint16_t RBTree<T>::max(uint16_t left, uint16_t right) const
865 {
866     return (left > right) ? left : right;
867 }
868
869 template <typename T>
870 bool RBTree<T>::rootIsNullptr() const
871 {
872     return mRoot==nullptr;
873 }
874
875 template <typename T>
876 T RBTree<T>::getRootKey() const
877 {
878     return (rootIsNullptr()) ? ~0ull : mRoot->mKey;
879 }
880
881 template <typename T>
882 uint8_t RBTree<T>::setKeyStrLen()
883 {
884     T i = *maximum();
885     do {
886         mKeyStrLen++;    // 打印结点占用的字符宽度,不含后缀(R、B),printGraph(node, keyStrLen)
887         i /= 10;
888     } while ( i > 0 );
889 //    mkeyStrLen = 0;
890
891     return mKeyStrLen;
892 }
893
894 }
895
896 #endif // RBTREE_H

main.cpp

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

原文地址:https://www.cnblogs.com/Dua677/p/10891660.html

时间: 2024-08-11 09:48:37

二叉树之红黑树(RBTree)的相关文章

红黑树 RBTree

概述:R-B Tree,又称为"红黑树".本文参考了<算法导论>中红黑树相关知识,加之自己的解,然后以图文的形式对红黑树进行说明.本文的主要内容包括:红黑树的特性,红黑树的时间复杂度和它的证明,红黑树的左旋.右旋.插入等操作. 1 R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为"红黑树",它一种特殊的二叉查找树.红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black). 红黑树的特性:(1)每个

二叉树与红黑树的java实现

二叉树的java实现 public class BinaryTree { /** * 根节点 */ private static Node root; static class Node { int key; Node left, right, parent; public Node(int key) { this.key = key; } } public BinaryTree(int key) { root = new Node(key); } /** * 中序遍历 * * @param n

java——红黑树 RBTree

对于完全随机的数据,普通的二分搜索树就很好用,只是在极端情况下会退化成链表. 对于查询较多的情况,avl树很好用. 红黑树牺牲了平衡性,但是它的统计性能更优(综合增删改查所有的操作). 红黑树java实现(不完整,没有进行删除节点的操作): (默认左倾红黑树) package RedBlackTree; //从任意一个节点到叶子节点,经过的黑色节点是一样的--红黑树是保持"黑平衡"的二叉树 //因为23树中的每一个节点到叶子节点的深度是相同的 //红黑树在严格意义上不是平衡二叉树,最大

红黑树(RBTREE)之上-------构造红黑树

该怎么说呢,现在写代码的速度还是很快的,很高兴,o(^▽^)o. 光棍节到了,早上没忍住,手贱了一般,看到*D的优惠,买了个机械键盘,晚上就到了,敲着还是很舒服的,和老婆炫耀了一把哈哈. 光棍节再去*mall买个,带着上班用. 正题,构造红黑树,就是节点的插入与调整,具体的理论我就不说了,图我也不画了,别人画的很好,我在纸上画的我自己都不想看.   贴几个网址作为参考吧: 参考的文档:1.http://www.cnblogs.com/zhb-php/p/5504481.html (推荐) 2.h

平衡搜索树--红黑树 RBTree

红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black. 通过对任何一条从根到叶子节点简单路径上的颜色来约束树的高度,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡. 红黑树是满足下面红黑性质的二叉搜索树: 1. 每个节点,不是红色就是黑色的 2. 根节点是黑色的 3. 如果一个节点是红色的,则它的两个子节点是黑色的(不存在连续的红色节点) 4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点. 思考:为什么满足上面

堆,二叉树,红黑树,B数。

堆的概念: 堆中某个节点的值总是不大于或不小于其父节点的值: 堆总是一棵完全二叉树. 以百度的一个面试题为例: 序列{9,12,17,30,50,20,60,65,4,19}构造为堆后,堆所对应的的中序遍历序列可能为 65,12,30,50,9,19,20,4,,17,60 65,12,30,9,50,19,4,20,17,60 65,9,30,12,19,50,4,20,17,60 65,12,9,30,50,4,20,9,17,60 一.序列构造成堆: 1:1~9都是,从上到下,从左到右堆积

HashMap、ConcurrentHashMap、二叉树、红黑树

HashMap: 数组+链表结构. HashMap是一个用于存储Key-Value键值对的集合,初始化长度16 每次拓展长度必须是2的幂 (为了服务于key映射到index的Hash算法index =  HashCode(Key) &  (Length - 1)).每一个键值对也叫做Entry.这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干,每个初始值都是null.当进行put操作时,为了使得数据均匀分布会对key进行hash操作再和 HashMap长度进行与

树/二叉树(哈夫曼树/红黑树)笔记

1.树是一种常用数据结构,它是非线性结构. 2.树中任一普通节点可以有0或者多个子节点,但只能有一个父节点. 根节点没有父节点, 叶子节点没有子节点. 3.二叉树: 1)每个节点最多只能有两个子树的有序树 2)左边的子树称为左子树 3)右边的子树成为右子树 4)一棵深度为k的二叉树,如果它包含了(2^k-1)个节点,就把这棵二叉树称为满二叉树 4.满二叉树的特点: 1)每一层上的节点数都是最大节点数,即各层为1,2,4,8,16 .... (2^k-1) 2)一棵有n个节点的二叉树,按满二叉树的

【转】B树、B-树、B+树、B*树、红黑树、 二叉排序树、trie树Double Array 字典查找树简介

B  树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中:否则,如果查询关键字比结点关键字小,就进入左儿子:如果比结点关键字大,就进入右儿子:如果左儿子或右儿子的指针为空,则报告找不到相应的关键字: 如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的搜索性