二叉树之红黑树(RBTree)

Posted Duacai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树之红黑树(RBTree)相关的知识,希望对你有一定的参考价值。

红黑树(RB-Tree)

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

  详解以后再补充。。。

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

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

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

 

 

红黑树插入删除步骤

 

输出

代码

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

工程通过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     二叉查找树之红黑树

算法红黑树-二叉树-算法

特化的AVL树之红黑树学习及原理解析

C++之红黑树

[转]数据结构中各种树

高效搜索数据结构之红黑树简介