vrchess
diff src/vr/rbtree.c @ 7:bd8202d6d28d
some progress...
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 22 Aug 2014 16:55:16 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/vr/rbtree.c Fri Aug 22 16:55:16 2014 +0300 1.3 @@ -0,0 +1,501 @@ 1.4 +/* 1.5 +rbtree - simple balanced binary search tree (red-black tree) library. 1.6 +Copyright (C) 2011-2014 John Tsiombikas <nuclear@member.fsf.org> 1.7 + 1.8 +rbtree is free software, feel free to use, modify, and redistribute it, under 1.9 +the terms of the 3-clause BSD license. See COPYING for details. 1.10 + */ 1.11 +#include <stdio.h> 1.12 +#include <stdlib.h> 1.13 +#include <stdint.h> 1.14 +#include <string.h> 1.15 +#include "rbtree.h" 1.16 + 1.17 +#define INT2PTR(x) ((void*)(intptr_t)(x)) 1.18 +#define PTR2INT(x) ((int)(intptr_t)(x)) 1.19 + 1.20 +struct rbtree { 1.21 + struct rbnode *root; 1.22 + 1.23 + rb_alloc_func_t alloc; 1.24 + rb_free_func_t free; 1.25 + 1.26 + rb_cmp_func_t cmp; 1.27 + rb_del_func_t del; 1.28 + void *del_cls; 1.29 + 1.30 + struct rbnode *rstack, *iter; 1.31 +}; 1.32 + 1.33 +static int cmpaddr(const void *ap, const void *bp); 1.34 +static int cmpint(const void *ap, const void *bp); 1.35 + 1.36 +static int count_nodes(struct rbnode *node); 1.37 +static void del_tree(struct rbnode *node, void (*delfunc)(struct rbnode*, void*), void *cls); 1.38 +static struct rbnode *insert(struct rbtree *rb, struct rbnode *tree, void *key, void *data); 1.39 +static struct rbnode *delete(struct rbtree *rb, struct rbnode *tree, void *key); 1.40 +/*static struct rbnode *find(struct rbtree *rb, struct rbnode *node, void *key);*/ 1.41 +static void traverse(struct rbnode *node, void (*func)(struct rbnode*, void*), void *cls); 1.42 + 1.43 +struct rbtree *rb_create(rb_cmp_func_t cmp_func) 1.44 +{ 1.45 + struct rbtree *rb; 1.46 + 1.47 + if(!(rb = malloc(sizeof *rb))) { 1.48 + return 0; 1.49 + } 1.50 + if(rb_init(rb, cmp_func) == -1) { 1.51 + free(rb); 1.52 + return 0; 1.53 + } 1.54 + return rb; 1.55 +} 1.56 + 1.57 +void rb_free(struct rbtree *rb) 1.58 +{ 1.59 + rb_destroy(rb); 1.60 + free(rb); 1.61 +} 1.62 + 1.63 + 1.64 +int rb_init(struct rbtree *rb, rb_cmp_func_t cmp_func) 1.65 +{ 1.66 + memset(rb, 0, sizeof *rb); 1.67 + 1.68 + if(cmp_func == RB_KEY_INT) { 1.69 + rb->cmp = cmpint; 1.70 + } else if(cmp_func == RB_KEY_STRING) { 1.71 + rb->cmp = (rb_cmp_func_t)strcmp; 1.72 + } else { 1.73 + rb->cmp = cmpaddr; 1.74 + } 1.75 + 1.76 + rb->alloc = malloc; 1.77 + rb->free = free; 1.78 + return 0; 1.79 +} 1.80 + 1.81 +void rb_destroy(struct rbtree *rb) 1.82 +{ 1.83 + del_tree(rb->root, rb->del, rb->del_cls); 1.84 +} 1.85 + 1.86 +void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free) 1.87 +{ 1.88 + rb->alloc = alloc; 1.89 + rb->free = free; 1.90 +} 1.91 + 1.92 + 1.93 +void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func) 1.94 +{ 1.95 + rb->cmp = func; 1.96 +} 1.97 + 1.98 +void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls) 1.99 +{ 1.100 + rb->del = func; 1.101 + rb->del_cls = cls; 1.102 +} 1.103 + 1.104 + 1.105 +void rb_clear(struct rbtree *rb) 1.106 +{ 1.107 + del_tree(rb->root, rb->del, rb->del_cls); 1.108 + rb->root = 0; 1.109 +} 1.110 + 1.111 +int rb_copy(struct rbtree *dest, struct rbtree *src) 1.112 +{ 1.113 + struct rbnode *node; 1.114 + 1.115 + rb_clear(dest); 1.116 + rb_begin(src); 1.117 + while((node = rb_next(src))) { 1.118 + if(rb_insert(dest, node->key, node->data) == -1) { 1.119 + return -1; 1.120 + } 1.121 + } 1.122 + return 0; 1.123 +} 1.124 + 1.125 +int rb_size(struct rbtree *rb) 1.126 +{ 1.127 + return count_nodes(rb->root); 1.128 +} 1.129 + 1.130 +int rb_insert(struct rbtree *rb, void *key, void *data) 1.131 +{ 1.132 + rb->root = insert(rb, rb->root, key, data); 1.133 + rb->root->red = 0; 1.134 + return 0; 1.135 +} 1.136 + 1.137 +int rb_inserti(struct rbtree *rb, int key, void *data) 1.138 +{ 1.139 + rb->root = insert(rb, rb->root, INT2PTR(key), data); 1.140 + rb->root->red = 0; 1.141 + return 0; 1.142 +} 1.143 + 1.144 + 1.145 +int rb_delete(struct rbtree *rb, void *key) 1.146 +{ 1.147 + rb->root = delete(rb, rb->root, key); 1.148 + rb->root->red = 0; 1.149 + return 0; 1.150 +} 1.151 + 1.152 +int rb_deletei(struct rbtree *rb, int key) 1.153 +{ 1.154 + rb->root = delete(rb, rb->root, INT2PTR(key)); 1.155 + rb->root->red = 0; 1.156 + return 0; 1.157 +} 1.158 + 1.159 + 1.160 +void *rb_find(struct rbtree *rb, void *key) 1.161 +{ 1.162 + struct rbnode *node = rb->root; 1.163 + 1.164 + while(node) { 1.165 + int cmp = rb->cmp(key, node->key); 1.166 + if(cmp == 0) { 1.167 + return node->data; 1.168 + } 1.169 + node = cmp < 0 ? node->left : node->right; 1.170 + } 1.171 + return 0; 1.172 +} 1.173 + 1.174 +void *rb_findi(struct rbtree *rb, int key) 1.175 +{ 1.176 + return rb_find(rb, INT2PTR(key)); 1.177 +} 1.178 + 1.179 + 1.180 +void rb_foreach(struct rbtree *rb, void (*func)(struct rbnode*, void*), void *cls) 1.181 +{ 1.182 + traverse(rb->root, func, cls); 1.183 +} 1.184 + 1.185 + 1.186 +struct rbnode *rb_root(struct rbtree *rb) 1.187 +{ 1.188 + return rb->root; 1.189 +} 1.190 + 1.191 +void rb_begin(struct rbtree *rb) 1.192 +{ 1.193 + rb->rstack = 0; 1.194 + rb->iter = rb->root; 1.195 +} 1.196 + 1.197 +#define push(sp, x) ((x)->next = (sp), (sp) = (x)) 1.198 +#define pop(sp) ((sp) = (sp)->next) 1.199 +#define top(sp) (sp) 1.200 + 1.201 +struct rbnode *rb_next(struct rbtree *rb) 1.202 +{ 1.203 + struct rbnode *res = 0; 1.204 + 1.205 + while(rb->rstack || rb->iter) { 1.206 + if(rb->iter) { 1.207 + push(rb->rstack, rb->iter); 1.208 + rb->iter = rb->iter->left; 1.209 + } else { 1.210 + rb->iter = top(rb->rstack); 1.211 + pop(rb->rstack); 1.212 + res = rb->iter; 1.213 + rb->iter = rb->iter->right; 1.214 + break; 1.215 + } 1.216 + } 1.217 + return res; 1.218 +} 1.219 + 1.220 +void *rb_node_key(struct rbnode *node) 1.221 +{ 1.222 + return node ? node->key : 0; 1.223 +} 1.224 + 1.225 +int rb_node_keyi(struct rbnode *node) 1.226 +{ 1.227 + return node ? PTR2INT(node->key) : 0; 1.228 +} 1.229 + 1.230 +void *rb_node_data(struct rbnode *node) 1.231 +{ 1.232 + return node ? node->data : 0; 1.233 +} 1.234 + 1.235 +static int cmpaddr(const void *ap, const void *bp) 1.236 +{ 1.237 + return ap < bp ? -1 : (ap > bp ? 1 : 0); 1.238 +} 1.239 + 1.240 +static int cmpint(const void *ap, const void *bp) 1.241 +{ 1.242 + return PTR2INT(ap) - PTR2INT(bp); 1.243 +} 1.244 + 1.245 + 1.246 +/* ---- left-leaning 2-3 red-black implementation ---- */ 1.247 + 1.248 +/* helper prototypes */ 1.249 +static int is_red(struct rbnode *tree); 1.250 +static void color_flip(struct rbnode *tree); 1.251 +static struct rbnode *rot_left(struct rbnode *a); 1.252 +static struct rbnode *rot_right(struct rbnode *a); 1.253 +static struct rbnode *find_min(struct rbnode *tree); 1.254 +static struct rbnode *del_min(struct rbtree *rb, struct rbnode *tree); 1.255 +/*static struct rbnode *move_red_right(struct rbnode *tree);*/ 1.256 +static struct rbnode *move_red_left(struct rbnode *tree); 1.257 +static struct rbnode *fix_up(struct rbnode *tree); 1.258 + 1.259 +static int count_nodes(struct rbnode *node) 1.260 +{ 1.261 + if(!node) 1.262 + return 0; 1.263 + 1.264 + return 1 + count_nodes(node->left) + count_nodes(node->right); 1.265 +} 1.266 + 1.267 +static void del_tree(struct rbnode *node, rb_del_func_t delfunc, void *cls) 1.268 +{ 1.269 + if(!node) 1.270 + return; 1.271 + 1.272 + del_tree(node->left, delfunc, cls); 1.273 + del_tree(node->right, delfunc, cls); 1.274 + 1.275 + if(delfunc) { 1.276 + delfunc(node, cls); 1.277 + } 1.278 + free(node); 1.279 +} 1.280 + 1.281 +static struct rbnode *insert(struct rbtree *rb, struct rbnode *tree, void *key, void *data) 1.282 +{ 1.283 + int cmp; 1.284 + 1.285 + if(!tree) { 1.286 + struct rbnode *node = rb->alloc(sizeof *node); 1.287 + node->red = 1; 1.288 + node->key = key; 1.289 + node->data = data; 1.290 + node->left = node->right = 0; 1.291 + return node; 1.292 + } 1.293 + 1.294 + cmp = rb->cmp(key, tree->key); 1.295 + 1.296 + if(cmp < 0) { 1.297 + tree->left = insert(rb, tree->left, key, data); 1.298 + } else if(cmp > 0) { 1.299 + tree->right = insert(rb, tree->right, key, data); 1.300 + } else { 1.301 + tree->data = data; 1.302 + } 1.303 + 1.304 + /* fix right-leaning reds */ 1.305 + if(is_red(tree->right)) { 1.306 + tree = rot_left(tree); 1.307 + } 1.308 + /* fix two reds in a row */ 1.309 + if(is_red(tree->left) && is_red(tree->left->left)) { 1.310 + tree = rot_right(tree); 1.311 + } 1.312 + 1.313 + /* if 4-node, split it by color inversion */ 1.314 + if(is_red(tree->left) && is_red(tree->right)) { 1.315 + color_flip(tree); 1.316 + } 1.317 + 1.318 + return tree; 1.319 +} 1.320 + 1.321 +static struct rbnode *delete(struct rbtree *rb, struct rbnode *tree, void *key) 1.322 +{ 1.323 + int cmp; 1.324 + 1.325 + if(!tree) { 1.326 + return 0; 1.327 + } 1.328 + 1.329 + cmp = rb->cmp(key, tree->key); 1.330 + 1.331 + if(cmp < 0) { 1.332 + if(!is_red(tree->left) && !is_red(tree->left->left)) { 1.333 + tree = move_red_left(tree); 1.334 + } 1.335 + tree->left = delete(rb, tree->left, key); 1.336 + } else { 1.337 + /* need reds on the right */ 1.338 + if(is_red(tree->left)) { 1.339 + tree = rot_right(tree); 1.340 + } 1.341 + 1.342 + /* found it at the bottom (XXX what certifies left is null?) */ 1.343 + if(cmp == 0 && !tree->right) { 1.344 + if(rb->del) { 1.345 + rb->del(tree, rb->del_cls); 1.346 + } 1.347 + rb->free(tree); 1.348 + return 0; 1.349 + } 1.350 + 1.351 + if(!is_red(tree->right) && !is_red(tree->right->left)) { 1.352 + tree = move_red_left(tree); 1.353 + } 1.354 + 1.355 + if(key == tree->key) { 1.356 + struct rbnode *rmin = find_min(tree->right); 1.357 + tree->key = rmin->key; 1.358 + tree->data = rmin->data; 1.359 + tree->right = del_min(rb, tree->right); 1.360 + } else { 1.361 + tree->right = delete(rb, tree->right, key); 1.362 + } 1.363 + } 1.364 + 1.365 + return fix_up(tree); 1.366 +} 1.367 + 1.368 +/*static struct rbnode *find(struct rbtree *rb, struct rbnode *node, void *key) 1.369 +{ 1.370 + int cmp; 1.371 + 1.372 + if(!node) 1.373 + return 0; 1.374 + 1.375 + if((cmp = rb->cmp(key, node->key)) == 0) { 1.376 + return node; 1.377 + } 1.378 + return find(rb, cmp < 0 ? node->left : node->right, key); 1.379 +}*/ 1.380 + 1.381 +static void traverse(struct rbnode *node, void (*func)(struct rbnode*, void*), void *cls) 1.382 +{ 1.383 + if(!node) 1.384 + return; 1.385 + 1.386 + traverse(node->left, func, cls); 1.387 + func(node, cls); 1.388 + traverse(node->right, func, cls); 1.389 +} 1.390 + 1.391 +/* helpers */ 1.392 + 1.393 +static int is_red(struct rbnode *tree) 1.394 +{ 1.395 + return tree && tree->red; 1.396 +} 1.397 + 1.398 +static void color_flip(struct rbnode *tree) 1.399 +{ 1.400 + tree->red = !tree->red; 1.401 + tree->left->red = !tree->left->red; 1.402 + tree->right->red = !tree->right->red; 1.403 +} 1.404 + 1.405 +static struct rbnode *rot_left(struct rbnode *a) 1.406 +{ 1.407 + struct rbnode *b = a->right; 1.408 + a->right = b->left; 1.409 + b->left = a; 1.410 + b->red = a->red; 1.411 + a->red = 1; 1.412 + return b; 1.413 +} 1.414 + 1.415 +static struct rbnode *rot_right(struct rbnode *a) 1.416 +{ 1.417 + struct rbnode *b = a->left; 1.418 + a->left = b->right; 1.419 + b->right = a; 1.420 + b->red = a->red; 1.421 + a->red = 1; 1.422 + return b; 1.423 +} 1.424 + 1.425 +static struct rbnode *find_min(struct rbnode *tree) 1.426 +{ 1.427 + struct rbnode *node = tree; 1.428 + 1.429 + if(!tree) 1.430 + return 0; 1.431 + 1.432 + while(node->left) { 1.433 + node = node->left; 1.434 + } 1.435 + return node; 1.436 +} 1.437 + 1.438 +static struct rbnode *del_min(struct rbtree *rb, struct rbnode *tree) 1.439 +{ 1.440 + if(!tree->left) { 1.441 + if(rb->del) { 1.442 + rb->del(tree->left, rb->del_cls); 1.443 + } 1.444 + rb->free(tree->left); 1.445 + return 0; 1.446 + } 1.447 + 1.448 + /* make sure we've got red (3/4-nodes) at the left side so we can delete at the bottom */ 1.449 + if(!is_red(tree->left) && !is_red(tree->left->left)) { 1.450 + tree = move_red_left(tree); 1.451 + } 1.452 + tree->left = del_min(rb, tree->left); 1.453 + 1.454 + /* fix right-reds, red-reds, and split 4-nodes on the way up */ 1.455 + return fix_up(tree); 1.456 +} 1.457 + 1.458 +#if 0 1.459 +/* push a red link on this node to the right */ 1.460 +static struct rbnode *move_red_right(struct rbnode *tree) 1.461 +{ 1.462 + /* flipping it makes both children go red, so we have a red to the right */ 1.463 + color_flip(tree); 1.464 + 1.465 + /* if after the flip we've got a red-red situation to the left, fix it */ 1.466 + if(is_red(tree->left->left)) { 1.467 + tree = rot_right(tree); 1.468 + color_flip(tree); 1.469 + } 1.470 + return tree; 1.471 +} 1.472 +#endif 1.473 + 1.474 +/* push a red link on this node to the left */ 1.475 +static struct rbnode *move_red_left(struct rbnode *tree) 1.476 +{ 1.477 + /* flipping it makes both children go red, so we have a red to the left */ 1.478 + color_flip(tree); 1.479 + 1.480 + /* if after the flip we've got a red-red on the right-left, fix it */ 1.481 + if(is_red(tree->right->left)) { 1.482 + tree->right = rot_right(tree->right); 1.483 + tree = rot_left(tree); 1.484 + color_flip(tree); 1.485 + } 1.486 + return tree; 1.487 +} 1.488 + 1.489 +static struct rbnode *fix_up(struct rbnode *tree) 1.490 +{ 1.491 + /* fix right-leaning */ 1.492 + if(is_red(tree->right)) { 1.493 + tree = rot_left(tree); 1.494 + } 1.495 + /* change invalid red-red pairs into a proper 4-node */ 1.496 + if(is_red(tree->left) && is_red(tree->left->left)) { 1.497 + tree = rot_right(tree); 1.498 + } 1.499 + /* split 4-nodes */ 1.500 + if(is_red(tree->left) && is_red(tree->right)) { 1.501 + color_flip(tree); 1.502 + } 1.503 + return tree; 1.504 +}