红黑树的代码实现

Posted xingkongyihao

tags:

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

红黑树满足一下规则

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

 

以上是关于红黑树的代码实现的主要内容,如果未能解决你的问题,请参考以下文章

[转]红黑树讲解

红黑树插入与删除完整代码(dart语言实现)

浅谈红黑树(C语言代码实现)

ConcurrentHashMap(JDK1.8)中红黑树的实现

红黑树的原理+实现

map和set的模拟实现