红黑树的代码实现

红黑树满足一下规则

1. 每个节点不是红色就是黑色

2.根节点为黑色

3.如果节点为红,其子节点必须为黑

4.任一节点至nil的任何路径,所包含的黑节点数必须相同。

5.叶子节点nil为黑色

 

当破坏了平衡时,在调整的时候需要用到左旋和右旋

左旋:

右旋:

 

代码实现:

 1 void rb_tree::__rb_tree_rotate_left(link_type x) {
 2     link_type y = x->right;
 3     x->right = y->left;
 4     if(y->left != nil) {
 5         y->left->parent = x;
 6     }
 7     y->parent = x->parent;
 8     if(x == root) {
 9         root = y;
10     } else if(x == x->parent->left) {
11         x->parent->left = y;
12     } else {
13         x->parent->right = y;
14     }
15     x->parent = y;
16     y->left = x;
17 }
左旋转
 1 void rb_tree::__rb_tree_rotate_right(link_type x) {
 2     link_type y = x->left;
 3     x->left = y->right;
 4     if(x->left != nil) {
 5         x->left->parent = x;
 6     }
 7     y->parent = x->parent;
 8     if(x == root) {
 9         root = y;
10     } else if(x->parent->left == x) {
11         x->parent->left = y;
12     } else {
13         x->parent->right = y;
14     }
15 
16     x->parent = y;
17     y->right = x;
18 }
右旋转

 

插入节点时,可能会破坏红黑树的结构,如下图,在插入3,8,35,75的时候,就破坏了树的结构:

 

 

设定如下用语:新节点为X,其父节点为P,组父节点为G,伯父节点为S,曾祖父节点GG。

根据红黑树规则4,X必为红,若P也为红(这就违反了规则3,必须调整树形),则G必为黑。于是,根据X的插入位置及外围节点的颜色,有了以下三种考虑。

 

情况1:S为黑且X为外侧插入。

对此情况,我们先对P,G做一次单旋转,并更改P,G的颜色,即可重新满足红黑树的规则3。

情况2:S为黑且X为内侧插入。

对此情况,我们必须先对P,X做一次单旋转并更改G,X颜色,再将结果对G做一次单旋转,即可重新满足红黑树规则3.

情况3:S为红,不考虑X是否内外测。

对此情况,我们需将P和S设置为黑色,G设置为红色,并将X设置成G继续判断即可。

 

以下为插入和调整代码

 1 void rb_tree::insert(key_type __x) {
 2     link_type new_node;
 3     link_type new_parent = nil;
 4     link_type pos = root;
 5     while (pos != nil) {
 6         new_parent = pos;
 7         if(__x < pos->key) {
 8             pos = pos->left;
 9         } else if(__x > pos->key) {
10             pos = pos->right;
11         } else {
12             fprintf(stderr, "Error: node %d already in the tree.\n", __x);
13             exit(1);
14         }
15     }
16     new_node = get_node(__x);
17     new_node->parent = new_parent;
18     if(new_parent == nil) {
19         root = new_node;
20     } else if(__x < new_parent->key) {
21         new_parent->left = new_node;
22     } else {
23         new_parent->right = new_node;
24     }
25     __rb_tree_rebalance(new_node);
26     ++ node_count;
27 }
插入
 1 void rb_tree::__rb_tree_rebalance(link_type x) {
 2     while (x != root && x->parent->color == __rb_tree_red) {
 3         if(x->parent == x->parent->parent->left) {
 4             link_type s = x->parent->parent->right;
 5             if(s && s->color == __rb_tree_red) {
 6                 x->parent->color = __rb_tree_black;
 7                 s->color = __rb_tree_black;
 8                 x->parent->parent->color = __rb_tree_red;
 9                 x = x->parent->parent;
10             } else {
11                 if(x == x->parent->right) {
12                     x = x->parent;
13                     __rb_tree_rotate_left(x);
14                 }
15                 x->parent->color = __rb_tree_black;
16                 x->parent->parent->color = __rb_tree_red;
17                 __rb_tree_rotate_right(x->parent->parent);
18             }
19         } else {
20             link_type s = x->parent->parent->left;
21             if(s && s->color == __rb_tree_red) {
22                 s->color = __rb_tree_black;
23                 x->parent->color = __rb_tree_black;
24                 x->parent->parent->color = __rb_tree_red;
25                 x = x->parent->parent;
26             } else {
27                 if(x == x->parent->left) {
28                     x = x->parent;
29                     __rb_tree_rotate_right(x);
30                 }
31                 x->parent->color = __rb_tree_black;
32                 x->parent->parent->color = __rb_tree_red;
33                 __rb_tree_rotate_left(x->parent->parent);
34             }
35         }
36     }
37     root->color = __rb_tree_black;
38 }
调整结构

 

删除节点的操作和二叉搜索树的原理一样,只是加了旋转和着色。

 1.当删除节点没有子节点树直接删除,用nil代替当前位置,

 2.当删除节点只有一个子树时,用子节点代替当前位置,

 3.当删除节点有两个字数时,找到它的后继节点,将它们继续更换,那么就变成了删除后继节点,而且后继节点至多有一个字数,这就转换成前两种情况了。

 

假设删除节点为y,子节点为x。

如果y是红色的,那就不会破坏结构。

如果y是黑色的,x是红色的,那么将x变为黑色就OK了

如果y是黑色的,x是黑色且是根,不会破坏结构。

否则的话就有下面四种情况:

 

情况1:X为黑色,S为红色。

如果X是P的左孩子,将S设置为黑色,X设置为红色,对P进行左旋装,重新设置S

如果X是P的右孩子,将S设置为黑色,X设置为红色,对P进行右旋转,重新设置S

 

情况2:X为黑色,S为黑色,并且S的两个孩子都为黑色。

将S设置为红色,设置X为P。

 

情况3:X为黑色,S为黑色。

如果X是P的左孩子,S的左孩子为红色,右孩子为黑色。

将S的左孩子设置为黑色,S设置为红色,对S进行右旋转,重新设置S。

如果X是P的右孩子,S的右孩子为红色,左孩子为黑色。

将S的右孩子设置为黑色,S设置为红色,对S进行左旋转,重新设置S。

 

情况4:X为黑色,S为黑色。

如果X是P的左孩子,S的右孩子为红色,左孩子任意。

将P的颜色赋值给S,设置P的颜色为黑色,S的右孩子为黑色,对P进行左旋转,设置X为root

如果X是P的右孩子,S的左孩子为红色,右孩子任意。

将P的颜色赋值给S,设置P的颜色为黑色,S的左孩子为红色,对P进行右旋转,设置X为root

 

其实X是P的左孩子或者右孩子,它们的操作都是对应的。

 

以下是删除代码和删除后调整的代码

 1 rb_tree::link_type rb_tree::erase(key_type __x) {
 2     link_type dead = find(__x);
 3     if(dead == nil) {
 4         fprintf(stderr, "Error,node %d does not exist\n", __x);
 5         return nil;
 6     }
 7     link_type x = nil, y = nil;
 8     if(dead->left == nil || dead->right == nil) {
 9         y = dead;
10     } else {
11         y = __get_next_node(dead);
12     }
13     if(y->left == nil) {
14         x = y->right;
15     }else if(y->right == nil) {
16         x = y->left;
17     }
18 //    if(x) {
19         x->parent = y->parent;
20 //    }
21     if(y->parent == nil) {
22         root = x;
23     } else if(y == y->parent->left) {
24         y->parent->left = x;
25     } else if(y == y->parent->right) {
26         y->parent->right = x;
27     }
28 
29     if(dead != y) {
30         dead->key = y->key;
31     }
32     if(y->color == __rb_tree_black) {
33         __rb_tree_delete_fixup(x);
34     }
35     return y;
36 }
删除
 1 void rb_tree::__rb_tree_delete_fixup(link_type x) {
 2 //    printf("nil:%d\n", x==nil);
 3     while (x != root && x->color == __rb_tree_black) {
 4         if(x == x->parent->left) {
 5             link_type s = x->parent->right;
 6             if(s->color == __rb_tree_red) {
 7                 s->color = __rb_tree_black;
 8                 x->parent->color = __rb_tree_red;
 9                 __rb_tree_rotate_left(x->parent);
10                 s = x->parent->right;
11             }
12 
13             if(s->left->color == __rb_tree_black && s->right->color == __rb_tree_black) {
14                 s->color = __rb_tree_red;
15                 x = x->parent;
16             } else {
17                 if(s->right->color == __rb_tree_black) {
18                     s->left->color = __rb_tree_black;
19                     s->color = __rb_tree_red;
20                     __rb_tree_rotate_right(s);
21                     s = x->parent->right;
22                 }
23 
24                 s->color = x->parent->color;
25                 x->parent->color = __rb_tree_black;
26                 s->right->color = __rb_tree_black;
27                 __rb_tree_rotate_left(x->parent);
28                 x = root;
29             }
30         } else {
31             link_type s = x->parent->left;
32             if(s->color == __rb_tree_red) {
33                 s->color = __rb_tree_black;
34                 x->parent->color = __rb_tree_red;
35                 __rb_tree_rotate_right(x->parent);
36                 s = x->parent->left;
37             }
38 
39             if(s->left->color == __rb_tree_black && s->right->color == __rb_tree_black) {
40                 s->color = __rb_tree_red;
41                 x = x->parent;
42             } else {
43                 if(s->left->color == __rb_tree_black) {
44                     s->right->color = __rb_tree_black;
45                     s->color = __rb_tree_red;
46                     __rb_tree_rotate_left(s);
47                     s = x->parent->left;
48                 }
49 
50                 s->color = x->parent->color;
51                 x->parent->color = __rb_tree_black;
52                 s->left->color = __rb_tree_black;
53                 __rb_tree_rotate_right(x->parent);
54                 x = root;
55             }
56         }
57     }
58     x->color = __rb_tree_black;
59 }
调整代码

 

 

以下是两个完整的代码,只需 #include "rb_tree.h"即可使用。

 1 //
 2 // Created by starry on 2019/8/24.
 3 //
 4 
 5 #ifndef TREE_PTR_H
 6 #define TREE_PTR_H
 7 
 8 #include <stdio.h>
 9 //#define nil NULL
10 
11 typedef bool __rb_tree_color_type;
12 const __rb_tree_color_type __rb_tree_red = false;
13 const __rb_tree_color_type __rb_tree_black = true;
14 
15 struct __rb_tree_node{
16     typedef __rb_tree_color_type color_type;
17     typedef __rb_tree_node* rb_node_ptr;
18     typedef int key_type;
19 
20     key_type key;
21     color_type color;
22     rb_node_ptr parent;
23     rb_node_ptr left, right;
24 };
25 
26 class rb_tree{
27 public:
28     typedef __rb_tree_node rb_tree_node;
29     typedef __rb_tree_color_type color_type;
30 
31     typedef rb_tree_node* link_type;
32     typedef size_t size_type;
33     typedef void* void_pointer;
34     typedef int key_type;
35 
36 public:
37     rb_tree();
38 
39     bool empty() const { return node_count == 0;}
40     size_type size() const { return node_count;}
41 
42     void clear();
43     void insert(key_type __x);
44     link_type erase(key_type __x);
45     link_type find(key_type __x);
46     void draw();
47     int rb_height(link_type x);
48 
49 private:
50 
51     link_type get_node(key_type __x);
52     void __rb_tree_rebalance(link_type x);
53     void __rb_tree_rotate_left(link_type x);
54     void __rb_tree_rotate_right(link_type x);
55     void __rb_tree_delete_fixup(link_type x);
56     void __serialize(link_type x);
57     void __delete(link_type x);
58     link_type __get_next_node(link_type x);
59 
60     size_type node_count;
61     link_type root;
62     link_type nil;
63 };
64 
65 
66 #endif //TREE_PTR_H
rb_tree.h
  1 //
  2 // Created by starry on 2019/8/24.
  3 //
  4 
  5 #include "rb_tree.h"
  6 #include <stdlib.h>
  7 #include <stdio.h>
  8 
  9 void rb_tree::draw() {
 10     __serialize(root);
 11     printf("\n");
 12 }
 13 
 14 int rb_tree::rb_height(link_type x) {
 15     if(x == nil)
 16         return 0;
 17     int l = rb_height(x->left);
 18     int r = rb_height(x->right);
 19     return 1 + (l>r?l:r);
 20 }
 21 
 22 rb_tree::rb_tree() {
 23     nil = (link_type)malloc(sizeof(rb_tree_node));
 24     nil->left = nil->right = nil->parent = nil;
 25     nil->color = __rb_tree_black;
 26     root = nil;
 27     node_count = 0;
 28 }
 29 
 30 void rb_tree::clear() {
 31     __delete(root);
 32     root = nil;
 33     node_count = 0;
 34 }
 35 
 36 void rb_tree::__delete(link_type x) {
 37     if(x == nil) return;
 38     __delete(x->left);
 39     __delete(x->right);
 40     free(x);
 41 }
 42 
 43 rb_tree::link_type rb_tree::find(key_type __x) {
 44     link_type pos = root;
 45     while (pos != nil) {
 46         if(pos->key == __x) return pos;
 47         else if(pos->key > __x) pos = pos->left;
 48         else if(pos->key < __x) pos = pos->right;
 49     }
 50     return pos;
 51 }
 52 
 53 void rb_tree::insert(key_type __x) {
 54     link_type new_node;
 55     link_type new_parent = nil;
 56     link_type pos = root;
 57     while (pos != nil) {
 58         new_parent = pos;
 59         if(__x < pos->key) {
 60             pos = pos->left;
 61         } else if(__x > pos->key) {
 62             pos = pos->right;
 63         } else {
 64             fprintf(stderr, "Error: node %d already in the tree.\n", __x);
 65             exit(1);
 66         }
 67     }
 68     new_node = get_node(__x);
 69     new_node->parent = new_parent;
 70     if(new_parent == nil) {
 71         root = new_node;
 72     } else if(__x < new_parent->key) {
 73         new_parent->left = new_node;
 74     } else {
 75         new_parent->right = new_node;
 76     }
 77     __rb_tree_rebalance(new_node);
 78     ++ node_count;
 79 }
 80 
 81 rb_tree::link_type rb_tree::erase(key_type __x) {
 82     link_type dead = find(__x);
 83     if(dead == nil) {
 84         fprintf(stderr, "Error,node %d does not exist\n", __x);
 85         return nil;
 86     }
 87     link_type x = nil, y = nil;
 88     if(dead->left == nil || dead->right == nil) {
 89         y = dead;
 90     } else {
 91         y = __get_next_node(dead);
 92     }
 93     if(y->left == nil) {
 94         x = y->right;
 95     }else if(y->right == nil) {
 96         x = y->left;
 97     }
 98 //    if(x) {
 99     x->parent = y->parent;
100 //    }
101     if(y->parent == nil) {
102         root = x;
103     } else if(y == y->parent->left) {
104         y->parent->left = x;
105     } else if(y == y->parent->right) {
106         y->parent->right = x;
107     }
108 
109     if(dead != y) {
110         dead->key = y->key;
111     }
112     if(y->color == __rb_tree_black) {
113         __rb_tree_delete_fixup(x);
114     }
115     return y;
116 }
117 
118 void rb_tree::__rb_tree_delete_fixup(link_type x) {
119     while (x != root && x->color == __rb_tree_black) {
120         if(x == x->parent->left) {
121             link_type s = x->parent->right;
122             if(s->color == __rb_tree_red) {
123                 s->color = __rb_tree_black;
124                 x->parent->color = __rb_tree_red;
125                 __rb_tree_rotate_left(x->parent);
126                 s = x->parent->right;
127             }
128 
129             if(s->left->color == __rb_tree_black && s->right->color == __rb_tree_black) {
130                 s->color = __rb_tree_red;
131                 x = x->parent;
132             } else {
133                 if(s->right->color == __rb_tree_black) {
134                     s->left->color = __rb_tree_black;
135                     s->color = __rb_tree_red;
136                     __rb_tree_rotate_right(s);
137                     s = x->parent->right;
138                 }
139 
140                 s->color = x->parent->color;
141                 x->parent->color = __rb_tree_black;
142                 s->right->color = __rb_tree_black;
143                 __rb_tree_rotate_left(x->parent);
144                 x = root;
145             }
146         } else {
147             link_type s = x->parent->left;
148             if(s->color == __rb_tree_red) {
149                 s->color = __rb_tree_black;
150                 x->parent->color = __rb_tree_red;
151                 __rb_tree_rotate_right(x->parent);
152                 s = x->parent->left;
153             }
154 
155             if(s->left->color == __rb_tree_black && s->right->color == __rb_tree_black) {
156                 s->color = __rb_tree_red;
157                 x = x->parent;
158             } else {
159                 if(s->left->color == __rb_tree_black) {
160                     s->right->color = __rb_tree_black;
161                     s->color = __rb_tree_red;
162                     __rb_tree_rotate_left(s);
163                     s = x->parent->left;
164                 }
165 
166                 s->color = x->parent->color;
167                 x->parent->color = __rb_tree_black;
168                 s->left->color = __rb_tree_black;
169                 __rb_tree_rotate_right(x->parent);
170                 x = root;
171             }
172         }
173     }
174     x->color = __rb_tree_black;
175 }
176 
177 rb_tree::link_type rb_tree::__get_next_node(link_type x) {
178     if(x == nil) return nil;
179     link_type next = nil;
180     if(x->right != nil) {
181         x = x->right;
182         while(x->left != nil) x = x->left;
183         next = x;
184     } else {
185         link_type y = x->parent;
186         while (y && x == y->right) {
187             x = y;
188             y = y->parent;
189         }
190         next = y;
191     }
192     return next;
193 }
194 
195 void rb_tree::__serialize(link_type x) {
196     if(x == nil) {
197         printf("#$");
198         return;
199     }
200     printf("(%d,%d)",x->key,x->color);
201     __serialize(x->left);
202     __serialize(x->right);
203 }
204 
205 rb_tree::link_type rb_tree::get_node(key_type __x) {
206     link_type ret;
207     if((ret = (link_type)malloc(sizeof(rb_tree_node))) == NULL) {
208         fprintf(stderr, "Error: out of memory.\n");
209         exit(1);
210     }
211     ret->left = nil;
212     ret->right = nil;
213     ret->parent = nil;
214     ret->color = __rb_tree_red;
215     ret->key = __x;
216     return ret;
217 }
218 
219 void rb_tree::__rb_tree_rebalance(link_type x) {
220     while (x != root && x->parent->color == __rb_tree_red) {
221         if(x->parent == x->parent->parent->left) {
222             link_type s = x->parent->parent->right;
223             if(s && s->color == __rb_tree_red) {
224                 x->parent->color = __rb_tree_black;
225                 s->color = __rb_tree_black;
226                 x->parent->parent->color = __rb_tree_red;
227                 x = x->parent->parent;
228             } else {
229                 if(x == x->parent->right) {
230                     x = x->parent;
231                     __rb_tree_rotate_left(x);
232                 }
233                 x->parent->color = __rb_tree_black;
234                 x->parent->parent->color = __rb_tree_red;
235                 __rb_tree_rotate_right(x->parent->parent);
236             }
237         } else {
238             link_type s = x->parent->parent->left;
239             if(s && s->color == __rb_tree_red) {
240                 s->color = __rb_tree_black;
241                 x->parent->color = __rb_tree_black;
242                 x->parent->parent->color = __rb_tree_red;
243                 x = x->parent->parent;
244             } else {
245                 if(x == x->parent->left) {
246                     x = x->parent;
247                     __rb_tree_rotate_right(x);
248                 }
249                 x->parent->color = __rb_tree_black;
250                 x->parent->parent->color = __rb_tree_red;
251                 __rb_tree_rotate_left(x->parent->parent);
252             }
253         }
254     }
255     root->color = __rb_tree_black;
256 }
257 
258 void rb_tree::__rb_tree_rotate_left(link_type x) {
259     link_type y = x->right;
260     x->right = y->left;
261     if(y->left != nil) {
262         y->left->parent = x;
263     }
264     y->parent = x->parent;
265     if(x == root) {
266         root = y;
267     } else if(x == x->parent->left) {
268         x->parent->left = y;
269     } else {
270         x->parent->right = y;
271     }
272     x->parent = y;
273     y->left = x;
274 }
275 
276 void rb_tree::__rb_tree_rotate_right(link_type x) {
277     link_type y = x->left;
278     x->left = y->right;
279     if(x->left != nil) {
280         x->left->parent = x;
281     }
282     y->parent = x->parent;
283     if(x == root) {
284         root = y;
285     } else if(x->parent->left == x) {
286         x->parent->left = y;
287     } else {
288         x->parent->right = y;
289     }
290 
291     x->parent = y;
292     y->right = x;
293 }
rb_tree.cpp

 

posted @ 2019-08-26 11:21  starry_sky  阅读(1826)  评论(0编辑  收藏  举报