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