tinywebd
diff src/rbtree.c @ 6:4f191dbfac7e
commited a bunch of missing files from previous commits
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 17 Apr 2015 01:57:25 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/rbtree.c Fri Apr 17 01:57:25 2015 +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) { 1.69 + rb->cmp = cmpaddr; 1.70 + } else if(cmp_func == RB_KEY_INT) { 1.71 + rb->cmp = cmpint; 1.72 + } else if(cmp_func == RB_KEY_STRING) { 1.73 + rb->cmp = (rb_cmp_func_t)strcmp; 1.74 + } else { 1.75 + rb->cmp = cmp_func; 1.76 + } 1.77 + 1.78 + rb->alloc = malloc; 1.79 + rb->free = free; 1.80 + return 0; 1.81 +} 1.82 + 1.83 +void rb_destroy(struct rbtree *rb) 1.84 +{ 1.85 + del_tree(rb->root, rb->del, rb->del_cls); 1.86 +} 1.87 + 1.88 +void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free) 1.89 +{ 1.90 + rb->alloc = alloc; 1.91 + rb->free = free; 1.92 +} 1.93 + 1.94 + 1.95 +void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func) 1.96 +{ 1.97 + rb->cmp = func; 1.98 +} 1.99 + 1.100 +void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls) 1.101 +{ 1.102 + rb->del = func; 1.103 + rb->del_cls = cls; 1.104 +} 1.105 + 1.106 + 1.107 +void rb_clear(struct rbtree *rb) 1.108 +{ 1.109 + del_tree(rb->root, rb->del, rb->del_cls); 1.110 + rb->root = 0; 1.111 +} 1.112 + 1.113 +int rb_copy(struct rbtree *dest, struct rbtree *src) 1.114 +{ 1.115 + struct rbnode *node; 1.116 + 1.117 + rb_clear(dest); 1.118 + rb_begin(src); 1.119 + while((node = rb_next(src))) { 1.120 + if(rb_insert(dest, node->key, node->data) == -1) { 1.121 + return -1; 1.122 + } 1.123 + } 1.124 + return 0; 1.125 +} 1.126 + 1.127 +int rb_size(struct rbtree *rb) 1.128 +{ 1.129 + return count_nodes(rb->root); 1.130 +} 1.131 + 1.132 +int rb_insert(struct rbtree *rb, void *key, void *data) 1.133 +{ 1.134 + rb->root = insert(rb, rb->root, key, data); 1.135 + rb->root->red = 0; 1.136 + return 0; 1.137 +} 1.138 + 1.139 +int rb_inserti(struct rbtree *rb, int key, void *data) 1.140 +{ 1.141 + rb->root = insert(rb, rb->root, INT2PTR(key), data); 1.142 + rb->root->red = 0; 1.143 + return 0; 1.144 +} 1.145 + 1.146 + 1.147 +int rb_delete(struct rbtree *rb, void *key) 1.148 +{ 1.149 + rb->root = delete(rb, rb->root, key); 1.150 + rb->root->red = 0; 1.151 + return 0; 1.152 +} 1.153 + 1.154 +int rb_deletei(struct rbtree *rb, int key) 1.155 +{ 1.156 + rb->root = delete(rb, rb->root, INT2PTR(key)); 1.157 + rb->root->red = 0; 1.158 + return 0; 1.159 +} 1.160 + 1.161 + 1.162 +struct rbnode *rb_find(struct rbtree *rb, void *key) 1.163 +{ 1.164 + struct rbnode *node = rb->root; 1.165 + 1.166 + while(node) { 1.167 + int cmp = rb->cmp(key, node->key); 1.168 + if(cmp == 0) { 1.169 + return node; 1.170 + } 1.171 + node = cmp < 0 ? node->left : node->right; 1.172 + } 1.173 + return 0; 1.174 +} 1.175 + 1.176 +struct rbnode *rb_findi(struct rbtree *rb, int key) 1.177 +{ 1.178 + return rb_find(rb, INT2PTR(key)); 1.179 +} 1.180 + 1.181 + 1.182 +void rb_foreach(struct rbtree *rb, void (*func)(struct rbnode*, void*), void *cls) 1.183 +{ 1.184 + traverse(rb->root, func, cls); 1.185 +} 1.186 + 1.187 + 1.188 +struct rbnode *rb_root(struct rbtree *rb) 1.189 +{ 1.190 + return rb->root; 1.191 +} 1.192 + 1.193 +void rb_begin(struct rbtree *rb) 1.194 +{ 1.195 + rb->rstack = 0; 1.196 + rb->iter = rb->root; 1.197 +} 1.198 + 1.199 +#define push(sp, x) ((x)->next = (sp), (sp) = (x)) 1.200 +#define pop(sp) ((sp) = (sp)->next) 1.201 +#define top(sp) (sp) 1.202 + 1.203 +struct rbnode *rb_next(struct rbtree *rb) 1.204 +{ 1.205 + struct rbnode *res = 0; 1.206 + 1.207 + while(rb->rstack || rb->iter) { 1.208 + if(rb->iter) { 1.209 + push(rb->rstack, rb->iter); 1.210 + rb->iter = rb->iter->left; 1.211 + } else { 1.212 + rb->iter = top(rb->rstack); 1.213 + pop(rb->rstack); 1.214 + res = rb->iter; 1.215 + rb->iter = rb->iter->right; 1.216 + break; 1.217 + } 1.218 + } 1.219 + return res; 1.220 +} 1.221 + 1.222 +void *rb_node_key(struct rbnode *node) 1.223 +{ 1.224 + return node ? node->key : 0; 1.225 +} 1.226 + 1.227 +int rb_node_keyi(struct rbnode *node) 1.228 +{ 1.229 + return node ? PTR2INT(node->key) : 0; 1.230 +} 1.231 + 1.232 +void *rb_node_data(struct rbnode *node) 1.233 +{ 1.234 + return node ? node->data : 0; 1.235 +} 1.236 + 1.237 +static int cmpaddr(const void *ap, const void *bp) 1.238 +{ 1.239 + return ap < bp ? -1 : (ap > bp ? 1 : 0); 1.240 +} 1.241 + 1.242 +static int cmpint(const void *ap, const void *bp) 1.243 +{ 1.244 + return PTR2INT(ap) - PTR2INT(bp); 1.245 +} 1.246 + 1.247 + 1.248 +/* ---- left-leaning 2-3 red-black implementation ---- */ 1.249 + 1.250 +/* helper prototypes */ 1.251 +static int is_red(struct rbnode *tree); 1.252 +static void color_flip(struct rbnode *tree); 1.253 +static struct rbnode *rot_left(struct rbnode *a); 1.254 +static struct rbnode *rot_right(struct rbnode *a); 1.255 +static struct rbnode *find_min(struct rbnode *tree); 1.256 +static struct rbnode *del_min(struct rbtree *rb, struct rbnode *tree); 1.257 +/*static struct rbnode *move_red_right(struct rbnode *tree);*/ 1.258 +static struct rbnode *move_red_left(struct rbnode *tree); 1.259 +static struct rbnode *fix_up(struct rbnode *tree); 1.260 + 1.261 +static int count_nodes(struct rbnode *node) 1.262 +{ 1.263 + if(!node) 1.264 + return 0; 1.265 + 1.266 + return 1 + count_nodes(node->left) + count_nodes(node->right); 1.267 +} 1.268 + 1.269 +static void del_tree(struct rbnode *node, rb_del_func_t delfunc, void *cls) 1.270 +{ 1.271 + if(!node) 1.272 + return; 1.273 + 1.274 + del_tree(node->left, delfunc, cls); 1.275 + del_tree(node->right, delfunc, cls); 1.276 + 1.277 + if(delfunc) { 1.278 + delfunc(node, cls); 1.279 + } 1.280 + free(node); 1.281 +} 1.282 + 1.283 +static struct rbnode *insert(struct rbtree *rb, struct rbnode *tree, void *key, void *data) 1.284 +{ 1.285 + int cmp; 1.286 + 1.287 + if(!tree) { 1.288 + struct rbnode *node = rb->alloc(sizeof *node); 1.289 + node->red = 1; 1.290 + node->key = key; 1.291 + node->data = data; 1.292 + node->left = node->right = 0; 1.293 + return node; 1.294 + } 1.295 + 1.296 + cmp = rb->cmp(key, tree->key); 1.297 + 1.298 + if(cmp < 0) { 1.299 + tree->left = insert(rb, tree->left, key, data); 1.300 + } else if(cmp > 0) { 1.301 + tree->right = insert(rb, tree->right, key, data); 1.302 + } else { 1.303 + tree->data = data; 1.304 + } 1.305 + 1.306 + /* fix right-leaning reds */ 1.307 + if(is_red(tree->right)) { 1.308 + tree = rot_left(tree); 1.309 + } 1.310 + /* fix two reds in a row */ 1.311 + if(is_red(tree->left) && is_red(tree->left->left)) { 1.312 + tree = rot_right(tree); 1.313 + } 1.314 + 1.315 + /* if 4-node, split it by color inversion */ 1.316 + if(is_red(tree->left) && is_red(tree->right)) { 1.317 + color_flip(tree); 1.318 + } 1.319 + 1.320 + return tree; 1.321 +} 1.322 + 1.323 +static struct rbnode *delete(struct rbtree *rb, struct rbnode *tree, void *key) 1.324 +{ 1.325 + int cmp; 1.326 + 1.327 + if(!tree) { 1.328 + return 0; 1.329 + } 1.330 + 1.331 + cmp = rb->cmp(key, tree->key); 1.332 + 1.333 + if(cmp < 0) { 1.334 + if(!is_red(tree->left) && !is_red(tree->left->left)) { 1.335 + tree = move_red_left(tree); 1.336 + } 1.337 + tree->left = delete(rb, tree->left, key); 1.338 + } else { 1.339 + /* need reds on the right */ 1.340 + if(is_red(tree->left)) { 1.341 + tree = rot_right(tree); 1.342 + } 1.343 + 1.344 + /* found it at the bottom (XXX what certifies left is null?) */ 1.345 + if(cmp == 0 && !tree->right) { 1.346 + if(rb->del) { 1.347 + rb->del(tree, rb->del_cls); 1.348 + } 1.349 + rb->free(tree); 1.350 + return 0; 1.351 + } 1.352 + 1.353 + if(!is_red(tree->right) && !is_red(tree->right->left)) { 1.354 + tree = move_red_left(tree); 1.355 + } 1.356 + 1.357 + if(key == tree->key) { 1.358 + struct rbnode *rmin = find_min(tree->right); 1.359 + tree->key = rmin->key; 1.360 + tree->data = rmin->data; 1.361 + tree->right = del_min(rb, tree->right); 1.362 + } else { 1.363 + tree->right = delete(rb, tree->right, key); 1.364 + } 1.365 + } 1.366 + 1.367 + return fix_up(tree); 1.368 +} 1.369 + 1.370 +/*static struct rbnode *find(struct rbtree *rb, struct rbnode *node, void *key) 1.371 +{ 1.372 + int cmp; 1.373 + 1.374 + if(!node) 1.375 + return 0; 1.376 + 1.377 + if((cmp = rb->cmp(key, node->key)) == 0) { 1.378 + return node; 1.379 + } 1.380 + return find(rb, cmp < 0 ? node->left : node->right, key); 1.381 +}*/ 1.382 + 1.383 +static void traverse(struct rbnode *node, void (*func)(struct rbnode*, void*), void *cls) 1.384 +{ 1.385 + if(!node) 1.386 + return; 1.387 + 1.388 + traverse(node->left, func, cls); 1.389 + func(node, cls); 1.390 + traverse(node->right, func, cls); 1.391 +} 1.392 + 1.393 +/* helpers */ 1.394 + 1.395 +static int is_red(struct rbnode *tree) 1.396 +{ 1.397 + return tree && tree->red; 1.398 +} 1.399 + 1.400 +static void color_flip(struct rbnode *tree) 1.401 +{ 1.402 + tree->red = !tree->red; 1.403 + tree->left->red = !tree->left->red; 1.404 + tree->right->red = !tree->right->red; 1.405 +} 1.406 + 1.407 +static struct rbnode *rot_left(struct rbnode *a) 1.408 +{ 1.409 + struct rbnode *b = a->right; 1.410 + a->right = b->left; 1.411 + b->left = a; 1.412 + b->red = a->red; 1.413 + a->red = 1; 1.414 + return b; 1.415 +} 1.416 + 1.417 +static struct rbnode *rot_right(struct rbnode *a) 1.418 +{ 1.419 + struct rbnode *b = a->left; 1.420 + a->left = b->right; 1.421 + b->right = a; 1.422 + b->red = a->red; 1.423 + a->red = 1; 1.424 + return b; 1.425 +} 1.426 + 1.427 +static struct rbnode *find_min(struct rbnode *tree) 1.428 +{ 1.429 + if(!tree) 1.430 + return 0; 1.431 + 1.432 + while(tree->left) { 1.433 + tree = tree->left; 1.434 + } 1.435 + return tree; 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 +}