• 红黑树(C语言实现)


          因为看内核的时候感觉红黑树挺有意思的,所以利用周末的时间来实现一下玩玩。红黑树的操作主要是插入和删除,而删除的时候需要考虑的情况更多一些。具体的操作就不在这里罗嗦了,百度文库里面有一个比较有好的文章,已经说的很明白了。

          在看具体的操作的时候有的人可能感觉有些情况是没有考虑到的如果没有这种感觉的人很有可能根本没有仔细地想)。但是那些遗漏的情况如果存在的话操作之前的红黑树将违反那几个规则

          写代码的时候很多次因为少考虑情况而导致错误,细节比较多,刚开始rb_node中没有指向父节点的指针写的快吐血然后还是加上了代码具体的含义可以结合文章和注释来看还是很好理解的)。下面的代码中可能还有没有考虑到的细节,欢迎拍砖。

      1 #include <stdio.h>
    2 #include <stdlib.h>
    3
    4 const int RED = 0;
    5 const int BLACK = 1;
    6
    7 struct rb_node{
    8 rb_node* lchild, *rchild, *parent;
    9 int key, colour;
    10 };
    11 rb_node* root;
    12
    13 rb_node* get_node(rb_node* parent, int key);
    14 void rb_insert(int key);
    15 rb_node* rb_search(int key);
    16 void rb_delete(int key);
    17 rb_node* clock_wise(rb_node* node);
    18 rb_node* counter_clock_wise(rb_node* node);
    19 void show_rb_tree(rb_node* node);
    20
    21 rb_node* get_node(rb_node* parent, int key){
    22 rb_node *tmp = (rb_node*)malloc(sizeof(rb_node));
    23 tmp->key = key;
    24 tmp->colour = RED;
    25 tmp->parent = parent;
    26 tmp->lchild = tmp->rchild = NULL;
    27 return tmp;
    28 }
    29
    30 rb_node* clock_wise(rb_node* node){
    31 if(node == NULL || node->lchild == NULL)
    32 return NULL;
    33
    34 rb_node *rb_1=node, *rb_2=node->lchild, *rb_3=node->lchild->rchild;
    35 if(rb_1->parent != NULL){
    36 if(rb_1->parent->lchild == rb_1)
    37 rb_1->parent->lchild = rb_2;
    38 else
    39 rb_1->parent->rchild = rb_2;
    40 }else if(rb_1 == root){
    41 root = rb_2;
    42 }
    43 rb_2->parent = rb_1->parent;
    44
    45 rb_1->parent = rb_2;
    46 rb_2->rchild = rb_1;
    47
    48 rb_1->lchild = rb_3;
    49 if(rb_3 != NULL)rb_3->parent = rb_1;
    50
    51 return rb_2;
    52 }
    53
    54 rb_node* counter_clock_wise(rb_node* node){
    55 if(node == NULL || node->rchild == NULL)
    56 return NULL;
    57
    58 rb_node *rb_1=node, *rb_2=node->rchild, *rb_3=node->rchild->lchild;
    59 if(rb_1->parent != NULL){
    60 if(rb_1->parent->lchild == rb_1)
    61 rb_1->parent->lchild = rb_2;
    62 else
    63 rb_1->parent->rchild = rb_2;
    64 }
    65 else if(rb_1 == root){
    66 root = rb_2;
    67 }
    68 rb_2->parent = rb_1->parent;
    69
    70 rb_1->parent = rb_2;
    71 rb_2->lchild = rb_1;
    72
    73 rb_1->rchild = rb_3;
    74 if(rb_3 != NULL)rb_3->parent = rb_1;
    75
    76 return rb_2;
    77 }
    78
    79 rb_node* rb_search(int key){
    80 rb_node *p = root;
    81 while(p != NULL){
    82 if(key < p->key)
    83 p = p->lchild;
    84 else if(key > p->key)
    85 p = p->rchild;
    86 else
    87 break;
    88 }
    89 return p;
    90 }
    91
    92 void rb_insert(int key){
    93 rb_node *p=root, *q=NULL;
    94
    95 if(root == NULL){
    96 root = get_node(NULL, key);
    97 root->colour = BLACK;
    98 return;
    99 }
    100
    101 while(p != NULL){
    102 q = p;
    103 if(key < p->key)
    104 p = p->lchild;
    105 else if(key > p->key)
    106 p = p->rchild;
    107 else return;
    108 }
    109
    110 if(key < q->key)
    111 q->lchild = get_node(q, key);
    112 else
    113 q->rchild = get_node(q, key);
    114
    115 while(q != NULL && q->colour == RED){
    116 p = q->parent;//p won't null, or BUG.
    117
    118 if(p->lchild == q){
    119 if(q->rchild != NULL && q->rchild->colour == RED)
    120 counter_clock_wise(q);
    121 q = clock_wise(p);
    122 q->lchild->colour = BLACK;
    123 }
    124 else{
    125 if(q->lchild != NULL && q->lchild->colour == RED)
    126 clock_wise(q);
    127 q = counter_clock_wise(p);
    128 q->rchild->colour = BLACK;
    129 }
    130
    131 q = q->parent;
    132 }
    133 root->colour = BLACK;
    134 }
    135
    136 void show_rb_tree(rb_node* node){
    137 if(node == NULL)
    138 return;
    139 printf("(%d,%d)\n", node->key, node->colour);
    140 if(node->lchild != NULL){
    141 printf("[-1]\n");
    142 show_rb_tree(node->lchild);
    143 }
    144 if(node->rchild != NULL){
    145 printf("[1]\n");
    146 show_rb_tree(node->rchild);
    147 }
    148 printf("[0]\n");
    149 }
    150
    151 void rb_delete(int key){
    152 rb_node *v = rb_search(key), *u, *p, *c, *b;
    153 int tmp;
    154 if(v == NULL) return;
    155
    156 u = v;
    157 if(v->lchild != NULL && v->rchild != NULL){
    158 u = v->rchild;
    159 while(u->lchild != NULL){
    160 u = u->lchild;
    161 }
    162 tmp = u->key;
    163 u->key = v->key;
    164 v->key = tmp;
    165 }
    166
    167 //u is the node to free.
    168 if(u->lchild != NULL)
    169 c = u->lchild;
    170 else
    171 c = u->rchild;
    172
    173 p = u->parent;
    174 if(p != NULL){
    175 //remove u from rb_tree.
    176 if(p->lchild == u)
    177 p->lchild = c;
    178 else
    179 p->rchild = c;
    180 }
    181 else{
    182 //u is root.
    183 root = c;
    184 free((void*)u);
    185 return;
    186 }
    187
    188 //u is not root and u is RED, this will not unbalance.
    189 if(u->colour == RED){
    190 free((void*)u);
    191 return;
    192 }
    193
    194 free((void*)u);
    195 u = c;
    196
    197 //u is the first node to balance.
    198 while(u != root){
    199 if(u != NULL && u->colour == RED){
    200 //if u is RED, change it to BLACK can finsh.
    201 u->colour = BLACK;
    202 return;
    203 }
    204
    205 if(u == p->lchild)
    206 b = p->rchild;
    207 else
    208 b = p->lchild;
    209
    210 printf("%d\n", b->key);
    211
    212 //b is borther of u. b can't be null, or the rb_tree is must not balance.
    213 if(b->colour == BLACK){
    214 //If b's son is RED, rotate the node.
    215 if(b->lchild != NULL && b->lchild->colour == RED){
    216 if(u == p->lchild){
    217 b = clock_wise(b);
    218 b->colour = BLACK;
    219 b->rchild->colour = RED;
    220
    221 p = counter_clock_wise(p);
    222 p->colour = p->lchild->colour;
    223 p->lchild->colour = BLACK;
    224 p->rchild->colour = BLACK;
    225 }
    226 else{
    227 p = clock_wise(p);
    228 p->colour = p->rchild->colour;
    229 p->rchild->colour = BLACK;
    230 p->lchild->colour = BLACK;
    231 }
    232
    233 return;
    234 }
    235 else if(b->rchild != NULL && b->rchild->colour == RED){
    236 if(u == p->rchild){
    237 b = counter_clock_wise(b);
    238 b->colour = BLACK;
    239 b->lchild->colour = RED;
    240
    241 p = clock_wise(p);
    242 p->colour = p->rchild->colour;
    243 p->rchild->colour = BLACK;
    244 p->lchild->colour = BLACK;
    245 }
    246 else{
    247 p = counter_clock_wise(p);
    248 p->colour = p->lchild->colour;
    249 p->lchild->colour = BLACK;
    250 p->rchild->colour = BLACK;
    251 }
    252 return;
    253 }
    254 else{//if b's sons are BLACK, make b RED and move up u.
    255 b->colour = RED;
    256 u = p;
    257 p = u->parent;
    258 continue;
    259 }
    260 }
    261 else{
    262 if(u == p->lchild){
    263 p = counter_clock_wise(p);
    264 p->colour = BLACK;
    265 p->lchild->colour = RED;
    266 p = p->lchild;
    267 }
    268 else{
    269 p = clock_wise(p);
    270 p->colour = BLACK;
    271 p->rchild->colour = RED;
    272 p = p->rchild;
    273 }
    274 }
    275 }
    276 root->colour = BLACK;
    277 }
    278
    279 int main(){
    280 int i;
    281 root = NULL;
    282 for(i = 1; i <= 10; i++){
    283 rb_insert(i);
    284 }
    285 rb_delete(9);
    286 rb_delete(3);
    287 rb_delete(7);
    288 show_rb_tree(root);
    289 printf("\n");
    290 return 0;
    291 }
  • 相关阅读:
    TreeSelect组件:vmodel语法糖进行父子组件传值案例
    带 icon 的输入框:slot方式。slot="prefix"和slot="suffix"
    双向绑定vmodel与单向绑定vbind:value
    使用Set集合对List集合去重
    前端报错: error in ./src/assets/fonts/iconfont.svg?t=1523541245904,Module parse failed: Unexpected token (1:0),vue.config.js中引入chainWebpack后报错
    当主键不是id时,而是其他字段,那么该字段要加上@Id注解(除了表中指定主键,实体类中也要用@Id指定主键)
    java将文件转为base64字符串和将base64字符串转为文件
    父组件向子组件传递getList方法:provide/inject
    带卡片的input输入框
    C#中使用#if DEBUG
  • 原文地址:https://www.cnblogs.com/ggzwtj/p/2190420.html
Copyright © 2020-2023  润新知