RedBlack-Tree(红黑树)原理及C++代码实现

众所周知,红黑树是用途很广的平衡二叉搜索树,用过的都说好。所以我们来看看红黑树的是怎么实现的吧。

红黑树顾名思义,通过红与黑两种颜色来给每个节点上色。其中根结点和叶子结点一定是黑色的,并且红色结点的两个孩子一定是黑色的,每个结点到所有后代叶子的简单路径上,均包含相同数目的黑色结点(黑高bh)。

这里和其他树有些区别的是,红黑树的叶子结点并不包含关键字,它只是用来维持红黑树的性质。所以包含关键字的结点都是内部结点。

这样的性质也带来了很多有意思的现象。下面我们忽略所谓的叶子结点来看看。

1.红色结点的孩子要么没有,要么是两个黑色结点,不会有单个孩子结点的时候。

2.如果某个结点只有一个孩子结点,那么那个孩子结点一定是红色的。

3.用吸收的角度去看,即黑色结点可以吸收它的红色孩子结点,红黑树就像一个2-3-4树。

下面我们来看看代码吧,代码用了一个小技巧,即所有的叶子结点都用一个nil结点来表示,指向nullptr的指针现在全部指向nil。

代码如下:(仅供参考)

  1 #include <iostream>
  2 using namespace std;
  3 
  4 class RBT {
  5 private :
  6     enum {RED = 0, BLACK};
  7     struct Node {
  8         int key;
  9         bool color;
 10         Node * left;
 11         Node * right;
 12         Node * parent;
 13         Node(int k = 0, bool c = BLACK, Node *l = nullptr, Node *r = nullptr, Node *p = nullptr)
 14             : key(k), color(c), left(l), right(r), parent(p) {}
 15     };
 16 private :
 17     Node * nil;
 18     Node * root;
 19 private :
 20     void leftRotate(Node * x);
 21     void rightRotate(Node * x);
 22     void fixup_insert(Node * p);
 23     void fixup_remove(Node * p);
 24     void transplant(Node * old_t, Node * new_t);
 25     void insert(Node * p);
 26     void remove(Node * p);
 27     Node * search(Node * p, const int k);
 28     Node * minimum(Node * p);
 29     Node * maximum(Node * p);
 30     void inorderWalk(Node * p) const;
 31 public :
 32     RBT() : nil(new Node), root(nil) {}
 33     ~RBT() {delete nil;}
 34     void insert(const int key) {insert(new Node(key, RED, nil, nil, nil));}
 35     void remove(const int key) {remove(search(root, key));}
 36     bool search(const int key) {return (search(root, key) == nil ? false : true);}
 37     int minimum() {return minimum(root)->key;}
 38     int maximum() {return maximum(root)->key;}
 39     int predecessor(const int key);
 40     int successor(const int key);
 41 
 42 friend ostream &operator<<(ostream &os, const RBT &t);
 43 };
 44 
 45 void RBT::inorderWalk(Node * p) const {
 46     if (p != nil) {
 47         inorderWalk(p->left);
 48         cout << p->key << ' ';
 49         inorderWalk(p->right);
 50     }
 51 }
 52 
 53 RBT::Node * RBT::search(Node * p, const int k) {
 54     if (p == nil || k == p->key)
 55         return p;
 56     if (k < p->key)
 57         return search(p->left, k);
 58     else
 59         return search(p->right, k);
 60 }
 61 
 62 RBT::Node * RBT::minimum(Node * p) {
 63     if (p == nil)
 64         return p;
 65     while (p->left != nil)
 66         p = p->left;
 67     return p;
 68 }
 69 
 70 RBT::Node * RBT::maximum(Node * p) {
 71     if (p == nil)
 72         return p;
 73     while (p->right != nil)
 74         p = p->right;
 75     return p;
 76 }
 77 
 78 int RBT::predecessor(const int k) {
 79     Node * p = search(root, k);
 80     if (p == nil)
 81         return 0;
 82     if (p->left != nil)
 83         return maximum(p->left)->key;
 84     Node * y = p->parent;
 85     while (y != nil && y->left == p) {
 86         p = y;
 87         y = y->parent;
 88     }
 89     return y->key;
 90 }
 91 
 92 int RBT::successor(const int k) {
 93     Node * p = search(root, k);
 94     if (p == nil)
 95         return 0;
 96     if (p->right != nil)
 97         return minimum(p->right)->key;
 98     Node * y = p->parent;
 99     while (y != nil && y->right == p) {
100         p = y;
101         y = y->parent;
102     }
103     return y->key;
104 }
105 
106 void RBT::leftRotate(Node * x) { //assume:x->right != nil
107     Node * y = x->right;
108     x->right = y->left;
109     if (y->left != nil)
110         y->left->parent = x;
111     y->parent = x->parent;
112     if (x->parent == nil)
113         root = y;
114     else if (x == x->parent->left)
115         x->parent->left = y;
116     else
117         x->parent->right = y;
118     y->left = x;
119     x->parent = y;
120 }
121 
122 void RBT::rightRotate(Node * x) { //assume:x->left != nil
123     Node * y = x->left;
124     x->left = y->right;
125     if (y->right != nil)
126         y->right->parent = x;
127     y->parent = x->parent;
128     if (x->parent == nil)
129         root = y;
130     else if (x == x->parent->right)
131         x->parent->right = y;
132     else
133         x->parent->left = y;
134     y->right = x;
135     x->parent = y;
136 }
137 
138 void RBT::insert(Node * p) {
139     if (p == nullptr)
140         return ;
141     Node * x = root;
142     Node * y = nil;
143     while (x != nil) {
144         y = x;
145         if (x->key < p->key)
146             x = x->right;
147         else
148             x = x->left;
149     }
150     p->parent = y;
151     if (y == nil)
152         root = p;
153     else if (y->key < p->key)
154         y->right = p;
155     else
156         y->left = p;
157     fixup_insert(p);
158 }
159 
160 void RBT::fixup_insert(Node * p) {
161     while (p->parent->color == RED) {
162         if (p->parent == p->parent->parent->left) {
163             Node * y = p->parent->parent->right;
164             if (y->color == RED) { //case 1
165                 p->parent->color = BLACK;
166                 y->color = BLACK;
167                 p->parent->parent->color = RED;
168                 p = p->parent->parent;
169             }
170             else {
171                 if (p == p->parent->right) { //case 2
172                     p = p->parent;
173                     leftRotate(p);
174                 }
175                 p->parent->color = BLACK; //case 3
176                 p->parent->parent->color = RED;
177                 rightRotate(p->parent->parent);
178             }
179         }
180         else { //with "right" and "left" exchanged
181             Node * y = p->parent->parent->left;
182             if (y->color == RED) { //case 1
183                 p->parent->color = BLACK;
184                 y->color = BLACK;
185                 p->parent->parent->color = RED;
186                 p = p->parent->parent;
187             }
188             else {
189                 if (p == p->parent->left) { //case 2
190                     p = p->parent;
191                     rightRotate(p);
192                 }
193                 p->parent->color = BLACK; //case 3
194                 p->parent->parent->color = RED;
195                 leftRotate(p->parent->parent);
196             }
197         }
198     }
199     root->color = BLACK;
200 }
201 
202 void RBT::transplant(Node * old_t, Node * new_t) {
203     if (old_t->parent == nil)
204         root = new_t;
205     else if (old_t == old_t->parent->left)
206         old_t->parent->left = new_t;
207     else
208         old_t->parent->right = new_t;
209     new_t->parent = old_t->parent;
210 }
211 
212 void RBT::fixup_remove(Node * x) {
213     Node * z = nil;
214     while (x != root && x->color == BLACK) {
215         if (x == x->parent->left) {
216             z = x->parent->right;
217 /*case 1*/  if (z->color == RED) {
218                 z->color = BLACK;
219                 x->parent->color = RED;
220                 leftRotate(x->parent);
221                 z = x->parent->right; //new z
222             }
223 /*case 2*/  if (z->left->color == BLACK && z->right->color == BLACK) {
224                 z->color = RED;
225                 x = x->parent;
226             }
227             else {
228 /*case 3*/      if (z->right->color == BLACK) {
229                     z->left->color = BLACK;
230                     z->color = RED;
231                     rightRotate(z);
232                     z = x->parent->right;
233                 }
234 /*case 4*/      z->color = x->parent->color;
235                 x->parent->color = BLACK;
236                 z->right->color = BLACK;
237                 leftRotate(x->parent);
238                 x = root; //exit while
239             }
240         }
241         else {
242             z = x->parent->left;
243 /*case 1*/  if (z->color == RED) {
244                 z->color = BLACK;
245                 x->parent->color = RED;
246                 rightRotate(x->parent);
247                 z = x->parent->left; //new z
248             }
249 /*case 2*/  if (z->right->color == BLACK && z->left->color == BLACK) {
250                 z->color = RED;
251                 x = x->parent;
252             }
253             else {
254 /*case 3*/      if (z->left->color == BLACK) {
255                     z->right->color = BLACK;
256                     z->color = RED;
257                     leftRotate(z);
258                     z = x->parent->left;
259                 }
260 /*case 4*/      z->color = x->parent->color;
261                 x->parent->color = BLACK;
262                 z->left->color = BLACK;
263                 rightRotate(x->parent);
264                 x = root; //exit while
265             }
266         }
267     }
268     x->color = BLACK;
269 }
270 
271 void RBT::remove(Node * p) {
272     if (p == nil)
273         return ;
274     Node * y = p;
275     Node * x = nil;
276     bool y_originalColor = y->color;
277     if (p->left == nil) {
278         x = p->right;
279         transplant(p, p->right);
280     }
281     else if (p->right == nil) {
282         x = p->left;
283         transplant(p, p->left);
284     }
285     else {
286         y = minimum(p->right);
287         y_originalColor = y->color;
288         x = y->right;
289         if (y->parent == p)
290             x->parent = y;   //maybe x == nil
291         else {
292             transplant(y, y->right);
293             y->right = p->right;
294             y->right->parent = y;
295         }
296         transplant(p, y);
297         y->left = p->left;
298         y->left->parent = y;
299         y->color = p->color;
300     }
301     delete p;
302     if (y_originalColor == BLACK)
303         fixup_remove(x);
304 }
305 
306 ostream &operator<<(ostream &os, const RBT &t) {
307     t.inorderWalk(t.root);
308     return os;
309 }
posted @ 2020-01-16 16:09  简讯  阅读(628)  评论(0编辑  收藏  举报