紅黑樹的代碼實現


紅黑樹滿足一下規則

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM