├── Makefile ├── README.md ├── map.h ├── rbtree.c ├── rbtree.h └── test_map.c /Makefile: -------------------------------------------------------------------------------- 1 | all:map_test 2 | CFLAGS=-g -O0 -Wall 3 | 4 | map_test:test_map.o rbtree.o 5 | gcc -o $@ $^ $(CFLAGS) 6 | test_map.o:test_map.c 7 | rbtree.o:rbtree.h rbtree.c 8 | 9 | .PHONY:clean 10 | 11 | clean: 12 | rm *.o map_test 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Map for c 2 | Current Map Version 1.0 3 | For C++, there is STL to use, and so we have map to use. But for c, We have to implement ourselves. So I implement a C map, I used rb_tree to implement this. The map sort by the key, and get the value in O(logn). 4 | 5 | # Usage 6 | I grab rb_tree from linux kernel. Just import map.h, rbtree.h, rbtree.c in you project. 7 | 8 | # Example 9 | 10 | ```c 11 | 12 | //put the key and value into map 13 | root_t tree = RB_ROOT; 14 | char *key = "hello"; 15 | char *word = "world"; 16 | put(&tree, key, word); 17 | 18 | //get the value from key 19 | map_t *data = get(&tree, "zhang"); 20 | if (data != NULL) 21 | printf("%s\n", data->val); 22 | 23 | //Traversal 24 | map_t *node; 25 | for (node = map_first(&tree); node; node=map_next(&(node->node))) { 26 | printf("%s\n", node->val); 27 | } 28 | 29 | //Free map node 30 | if (data) { 31 | rb_erase(&data->node, &tree); 32 | map_free(data); 33 | } 34 | ```` 35 | 36 | # Bug Reporting and Feature Requests 37 | If you find a bug or have an enhancement request, simply file an Issue and send a message (via github messages) to the Committers to the project to let them know that you have filed an Issue. 38 | 39 | # Contact 40 | tjbroadroad@163.com 41 | 42 | 43 | -------------------------------------------------------------------------------- /map.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 zkdnfcf, Inc. All Rights Reserved 4 | * $Id$ 5 | * 6 | **************************************************************************/ 7 | 8 | /** 9 | * @file hash.h 10 | * @author zk(zkdnfc@163.com) 11 | * @date 2016/05/31 18:26:01 12 | * @version $Revision$ 13 | * @brief 14 | * 15 | **/ 16 | #ifndef _MAP_H 17 | #define _MAP_H 18 | 19 | #include "rbtree.h" 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | struct map { 26 | struct rb_node node; 27 | char *key; 28 | char *val; 29 | }; 30 | 31 | typedef struct map map_t; 32 | typedef struct rb_root root_t; 33 | typedef struct rb_node rb_node_t; 34 | 35 | map_t *get(root_t *root, char *str) { 36 | rb_node_t *node = root->rb_node; 37 | while (node) { 38 | map_t *data = container_of(node, map_t, node); 39 | 40 | //compare between the key with the keys in map 41 | int cmp = strcmp(str, data->key); 42 | if (cmp < 0) { 43 | node = node->rb_left; 44 | }else if (cmp > 0) { 45 | node = node->rb_right; 46 | }else { 47 | return data; 48 | } 49 | } 50 | return NULL; 51 | } 52 | 53 | int put(root_t *root, char* key, char* val) { 54 | map_t *data = (map_t*)malloc(sizeof(map_t)); 55 | data->key = (char*)malloc((strlen(key)+1)*sizeof(char)); 56 | strcpy(data->key, key); 57 | data->val = (char*)malloc((strlen(val)+1)*sizeof(char)); 58 | strcpy(data->val, val); 59 | 60 | rb_node_t **new_node = &(root->rb_node), *parent = NULL; 61 | while (*new_node) { 62 | map_t *this_node = container_of(*new_node, map_t, node); 63 | int result = strcmp(key, this_node->key); 64 | parent = *new_node; 65 | 66 | if (result < 0) { 67 | new_node = &((*new_node)->rb_left); 68 | }else if (result > 0) { 69 | new_node = &((*new_node)->rb_right); 70 | }else { 71 | strcpy(this_node->val, val); 72 | free(data); 73 | return 0; 74 | } 75 | } 76 | 77 | rb_link_node(&data->node, parent, new_node); 78 | rb_insert_color(&data->node, root); 79 | 80 | return 1; 81 | } 82 | 83 | map_t *map_first(root_t *tree) { 84 | rb_node_t *node = rb_first(tree); 85 | return (rb_entry(node, map_t, node)); 86 | } 87 | 88 | map_t *map_next(rb_node_t *node) { 89 | rb_node_t *next = rb_next(node); 90 | return rb_entry(next, map_t, node); 91 | } 92 | 93 | void map_free(map_t *node){ 94 | if (node != NULL) { 95 | if (node->key != NULL) { 96 | free(node->key); 97 | node->key = NULL; 98 | free(node->val); 99 | node->val = NULL; 100 | } 101 | free(node); 102 | node = NULL; 103 | } 104 | } 105 | 106 | #endif //_MAP_H 107 | 108 | /* vim: set ts=4 sw=4 sts=4 tw=100 */ 109 | -------------------------------------------------------------------------------- /rbtree.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 grab from kernel, Inc. All Rights Reserved 4 | **************************************************************************/ 5 | /* 6 | Red Black Trees 7 | (C) 1999 Andrea Arcangeli 8 | (C) 2002 David Woodhouse 9 | 10 | This program is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation; either version 2 of the License, or 13 | (at your option) any later version. 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | linux/lib/rbtree.c 22 | */ 23 | 24 | #include "rbtree.h" 25 | 26 | static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) 27 | { 28 | struct rb_node *right = node->rb_right; 29 | struct rb_node *parent = rb_parent(node); 30 | 31 | if ((node->rb_right = right->rb_left)) 32 | rb_set_parent(right->rb_left, node); 33 | right->rb_left = node; 34 | 35 | rb_set_parent(right, parent); 36 | 37 | if (parent) 38 | { 39 | if (node == parent->rb_left) 40 | parent->rb_left = right; 41 | else 42 | parent->rb_right = right; 43 | } 44 | else 45 | root->rb_node = right; 46 | rb_set_parent(node, right); 47 | } 48 | 49 | static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) 50 | { 51 | struct rb_node *left = node->rb_left; 52 | struct rb_node *parent = rb_parent(node); 53 | 54 | if ((node->rb_left = left->rb_right)) 55 | rb_set_parent(left->rb_right, node); 56 | left->rb_right = node; 57 | 58 | rb_set_parent(left, parent); 59 | 60 | if (parent) 61 | { 62 | if (node == parent->rb_right) 63 | parent->rb_right = left; 64 | else 65 | parent->rb_left = left; 66 | } 67 | else 68 | root->rb_node = left; 69 | rb_set_parent(node, left); 70 | } 71 | 72 | void rb_insert_color(struct rb_node *node, struct rb_root *root) 73 | { 74 | struct rb_node *parent, *gparent; 75 | 76 | while ((parent = rb_parent(node)) && rb_is_red(parent)) 77 | { 78 | gparent = rb_parent(parent); 79 | 80 | if (parent == gparent->rb_left) 81 | { 82 | { 83 | register struct rb_node *uncle = gparent->rb_right; 84 | if (uncle && rb_is_red(uncle)) 85 | { 86 | rb_set_black(uncle); 87 | rb_set_black(parent); 88 | rb_set_red(gparent); 89 | node = gparent; 90 | continue; 91 | } 92 | } 93 | 94 | if (parent->rb_right == node) 95 | { 96 | register struct rb_node *tmp; 97 | __rb_rotate_left(parent, root); 98 | tmp = parent; 99 | parent = node; 100 | node = tmp; 101 | } 102 | 103 | rb_set_black(parent); 104 | rb_set_red(gparent); 105 | __rb_rotate_right(gparent, root); 106 | } else { 107 | { 108 | register struct rb_node *uncle = gparent->rb_left; 109 | if (uncle && rb_is_red(uncle)) 110 | { 111 | rb_set_black(uncle); 112 | rb_set_black(parent); 113 | rb_set_red(gparent); 114 | node = gparent; 115 | continue; 116 | } 117 | } 118 | 119 | if (parent->rb_left == node) 120 | { 121 | register struct rb_node *tmp; 122 | __rb_rotate_right(parent, root); 123 | tmp = parent; 124 | parent = node; 125 | node = tmp; 126 | } 127 | 128 | rb_set_black(parent); 129 | rb_set_red(gparent); 130 | __rb_rotate_left(gparent, root); 131 | } 132 | } 133 | 134 | rb_set_black(root->rb_node); 135 | } 136 | 137 | static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, 138 | struct rb_root *root) 139 | { 140 | struct rb_node *other; 141 | 142 | while ((!node || rb_is_black(node)) && node != root->rb_node) 143 | { 144 | if (parent->rb_left == node) 145 | { 146 | other = parent->rb_right; 147 | if (rb_is_red(other)) 148 | { 149 | rb_set_black(other); 150 | rb_set_red(parent); 151 | __rb_rotate_left(parent, root); 152 | other = parent->rb_right; 153 | } 154 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 155 | (!other->rb_right || rb_is_black(other->rb_right))) 156 | { 157 | rb_set_red(other); 158 | node = parent; 159 | parent = rb_parent(node); 160 | } 161 | else 162 | { 163 | if (!other->rb_right || rb_is_black(other->rb_right)) 164 | { 165 | rb_set_black(other->rb_left); 166 | rb_set_red(other); 167 | __rb_rotate_right(other, root); 168 | other = parent->rb_right; 169 | } 170 | rb_set_color(other, rb_color(parent)); 171 | rb_set_black(parent); 172 | rb_set_black(other->rb_right); 173 | __rb_rotate_left(parent, root); 174 | node = root->rb_node; 175 | break; 176 | } 177 | } 178 | else 179 | { 180 | other = parent->rb_left; 181 | if (rb_is_red(other)) 182 | { 183 | rb_set_black(other); 184 | rb_set_red(parent); 185 | __rb_rotate_right(parent, root); 186 | other = parent->rb_left; 187 | } 188 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 189 | (!other->rb_right || rb_is_black(other->rb_right))) 190 | { 191 | rb_set_red(other); 192 | node = parent; 193 | parent = rb_parent(node); 194 | } 195 | else 196 | { 197 | if (!other->rb_left || rb_is_black(other->rb_left)) 198 | { 199 | rb_set_black(other->rb_right); 200 | rb_set_red(other); 201 | __rb_rotate_left(other, root); 202 | other = parent->rb_left; 203 | } 204 | rb_set_color(other, rb_color(parent)); 205 | rb_set_black(parent); 206 | rb_set_black(other->rb_left); 207 | __rb_rotate_right(parent, root); 208 | node = root->rb_node; 209 | break; 210 | } 211 | } 212 | } 213 | if (node) 214 | rb_set_black(node); 215 | } 216 | 217 | void rb_erase(struct rb_node *node, struct rb_root *root) 218 | { 219 | struct rb_node *child, *parent; 220 | int color; 221 | 222 | if (!node->rb_left) 223 | child = node->rb_right; 224 | else if (!node->rb_right) 225 | child = node->rb_left; 226 | else 227 | { 228 | struct rb_node *old = node, *left; 229 | 230 | node = node->rb_right; 231 | while ((left = node->rb_left) != NULL) 232 | node = left; 233 | 234 | if (rb_parent(old)) { 235 | if (rb_parent(old)->rb_left == old) 236 | rb_parent(old)->rb_left = node; 237 | else 238 | rb_parent(old)->rb_right = node; 239 | } else 240 | root->rb_node = node; 241 | 242 | child = node->rb_right; 243 | parent = rb_parent(node); 244 | color = rb_color(node); 245 | 246 | if (parent == old) { 247 | parent = node; 248 | } else { 249 | if (child) 250 | rb_set_parent(child, parent); 251 | parent->rb_left = child; 252 | 253 | node->rb_right = old->rb_right; 254 | rb_set_parent(old->rb_right, node); 255 | } 256 | 257 | node->rb_parent_color = old->rb_parent_color; 258 | node->rb_left = old->rb_left; 259 | rb_set_parent(old->rb_left, node); 260 | 261 | goto color; 262 | } 263 | 264 | 265 | parent = rb_parent(node); 266 | color = rb_color(node); 267 | 268 | if (child) 269 | rb_set_parent(child, parent); 270 | if (parent) 271 | { 272 | if (parent->rb_left == node) 273 | parent->rb_left = child; 274 | else 275 | parent->rb_right = child; 276 | } 277 | else 278 | root->rb_node = child; 279 | 280 | color: 281 | if (color == RB_BLACK) 282 | __rb_erase_color(child, parent, root); 283 | } 284 | 285 | 286 | static void rb_augment_path(struct rb_node *node, rb_augment_f func, void *data) 287 | { 288 | struct rb_node *parent; 289 | 290 | up: 291 | func(node, data); 292 | parent = rb_parent(node); 293 | if (!parent) 294 | return; 295 | 296 | if (node == parent->rb_left && parent->rb_right) 297 | func(parent->rb_right, data); 298 | else if (parent->rb_left) 299 | func(parent->rb_left, data); 300 | 301 | node = parent; 302 | goto up; 303 | } 304 | 305 | 306 | /* 307 | * after inserting @node into the tree, update the tree to account for 308 | * both the new entry and any damage done by rebalance 309 | */ 310 | void rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data) 311 | { 312 | if (node->rb_left) 313 | node = node->rb_left; 314 | else if (node->rb_right) 315 | node = node->rb_right; 316 | 317 | rb_augment_path(node, func, data); 318 | } 319 | 320 | /* 321 | * before removing the node, find the deepest node on the rebalance path 322 | * that will still be there after @node gets removed 323 | */ 324 | struct rb_node *rb_augment_erase_begin(struct rb_node *node) 325 | { 326 | struct rb_node *deepest; 327 | 328 | if (!node->rb_right && !node->rb_left) 329 | deepest = rb_parent(node); 330 | else if (!node->rb_right) 331 | deepest = node->rb_left; 332 | else if (!node->rb_left) 333 | deepest = node->rb_right; 334 | else { 335 | deepest = rb_next(node); 336 | if (deepest->rb_right) 337 | deepest = deepest->rb_right; 338 | else if (rb_parent(deepest) != node) 339 | deepest = rb_parent(deepest); 340 | } 341 | 342 | return deepest; 343 | } 344 | 345 | /* 346 | * after removal, update the tree to account for the removed entry 347 | * and any rebalance damage. 348 | */ 349 | void rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data) 350 | { 351 | if (node) 352 | rb_augment_path(node, func, data); 353 | } 354 | 355 | /* 356 | * This function returns the first node (in sort order) of the tree. 357 | */ 358 | struct rb_node *rb_first(const struct rb_root *root) 359 | { 360 | struct rb_node *n; 361 | 362 | n = root->rb_node; 363 | if (!n) 364 | return NULL; 365 | while (n->rb_left) 366 | n = n->rb_left; 367 | return n; 368 | } 369 | 370 | struct rb_node *rb_last(const struct rb_root *root) 371 | { 372 | struct rb_node *n; 373 | 374 | n = root->rb_node; 375 | if (!n) 376 | return NULL; 377 | while (n->rb_right) 378 | n = n->rb_right; 379 | return n; 380 | } 381 | 382 | struct rb_node *rb_next(const struct rb_node *node) 383 | { 384 | struct rb_node *parent; 385 | 386 | if (rb_parent(node) == node) 387 | return NULL; 388 | 389 | /* If we have a right-hand child, go down and then left as far 390 | as we can. */ 391 | if (node->rb_right) { 392 | node = node->rb_right; 393 | while (node->rb_left) 394 | node=node->rb_left; 395 | return (struct rb_node *)node; 396 | } 397 | 398 | /* No right-hand children. Everything down and left is 399 | smaller than us, so any 'next' node must be in the general 400 | direction of our parent. Go up the tree; any time the 401 | ancestor is a right-hand child of its parent, keep going 402 | up. First time it's a left-hand child of its parent, said 403 | parent is our 'next' node. */ 404 | while ((parent = rb_parent(node)) && node == parent->rb_right) 405 | node = parent; 406 | 407 | return parent; 408 | } 409 | 410 | struct rb_node *rb_prev(const struct rb_node *node) 411 | { 412 | struct rb_node *parent; 413 | 414 | if (rb_parent(node) == node) 415 | return NULL; 416 | 417 | /* If we have a left-hand child, go down and then right as far 418 | as we can. */ 419 | if (node->rb_left) { 420 | node = node->rb_left; 421 | while (node->rb_right) 422 | node=node->rb_right; 423 | return (struct rb_node *)node; 424 | } 425 | 426 | /* No left-hand children. Go up till we find an ancestor which 427 | is a right-hand child of its parent */ 428 | while ((parent = rb_parent(node)) && node == parent->rb_left) 429 | node = parent; 430 | 431 | return parent; 432 | } 433 | 434 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, 435 | struct rb_root *root) 436 | { 437 | struct rb_node *parent = rb_parent(victim); 438 | 439 | /* Set the surrounding nodes to point to the replacement */ 440 | if (parent) { 441 | if (victim == parent->rb_left) 442 | parent->rb_left = new; 443 | else 444 | parent->rb_right = new; 445 | } else { 446 | root->rb_node = new; 447 | } 448 | if (victim->rb_left) 449 | rb_set_parent(victim->rb_left, new); 450 | if (victim->rb_right) 451 | rb_set_parent(victim->rb_right, new); 452 | 453 | /* Copy the pointers/colour from the victim to the replacement */ 454 | *new = *victim; 455 | } 456 | 457 | /* vim: set ts=4 sw=4 sts=4 tw=100 */ 458 | -------------------------------------------------------------------------------- /rbtree.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 grab from kernel, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | /* 7 | Red Black Trees 8 | (C) 1999 Andrea Arcangeli 9 | 10 | This program is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation; either version 2 of the License, or 13 | (at your option) any later version. 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | linux/include/linux/rbtree.h 22 | To use rbtrees you'll have to implement your own insert and search cores. 23 | This will avoid us to use callbacks and to drop drammatically performances. 24 | I know it's not the cleaner way, but in C (not in C++) to get 25 | performances and genericity... 26 | Some example of insert and search follows here. The search is a plain 27 | normal search over an ordered tree. The insert instead must be implemented 28 | in two steps: First, the code must insert the element in order as a red leaf 29 | in the tree, and then the support library function rb_insert_color() must 30 | be called. Such function will do the not trivial work to rebalance the 31 | rbtree, if necessary. 32 | ----------------------------------------------------------------------- 33 | static inline struct page * rb_search_page_cache(struct inode * inode, 34 | unsigned long offset) 35 | { 36 | struct rb_node * n = inode->i_rb_page_cache.rb_node; 37 | struct page * page; 38 | while (n) 39 | { 40 | page = rb_entry(n, struct page, rb_page_cache); 41 | if (offset < page->offset) 42 | n = n->rb_left; 43 | else if (offset > page->offset) 44 | n = n->rb_right; 45 | else 46 | return page; 47 | } 48 | return NULL; 49 | } 50 | 51 | 52 | static inline struct page * __rb_insert_page_cache(struct inode * inode, 53 | unsigned long offset, 54 | struct rb_node * node) 55 | { 56 | struct rb_node ** p = &inode->i_rb_page_cache.rb_node; 57 | struct rb_node * parent = NULL; 58 | struct page * page; 59 | while (*p) 60 | { 61 | parent = *p; 62 | page = rb_entry(parent, struct page, rb_page_cache); 63 | if (offset < page->offset) 64 | p = &(*p)->rb_left; 65 | else if (offset > page->offset) 66 | p = &(*p)->rb_right; 67 | else 68 | return page; 69 | } 70 | rb_link_node(node, parent, p); 71 | return NULL; 72 | } 73 | 74 | 75 | static inline struct page * rb_insert_page_cache(struct inode * inode, 76 | unsigned long offset, 77 | struct rb_node * node) 78 | { 79 | struct page * ret; 80 | if ((ret = __rb_insert_page_cache(inode, offset, node))) 81 | goto out; 82 | rb_insert_color(node, &inode->i_rb_page_cache); 83 | out: 84 | return ret; 85 | } 86 | ----------------------------------------------------------------------- 87 | */ 88 | 89 | #ifndef _LINUX_RBTREE_H 90 | #define _LINUX_RBTREE_H 91 | 92 | #if defined(container_of) 93 | #undef container_of 94 | #define container_of(ptr, type, member) ({ \ 95 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 96 | (type *)( (char *)__mptr - offsetof(type,member) );}) 97 | #else 98 | #define container_of(ptr, type, member) ({ \ 99 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 100 | (type *)( (char *)__mptr - offsetof(type,member) );}) 101 | #endif 102 | 103 | #if defined(offsetof) 104 | #undef offsetof 105 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 106 | #else 107 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 108 | #endif 109 | 110 | #undef NULL 111 | #if defined(__cplusplus) 112 | #define NULL 0 113 | #else 114 | #define NULL ((void *)0) 115 | #endif 116 | 117 | struct rb_node 118 | { 119 | unsigned long rb_parent_color; 120 | #define RB_RED 0 121 | #define RB_BLACK 1 122 | struct rb_node *rb_right; 123 | struct rb_node *rb_left; 124 | } __attribute__((aligned(sizeof(long)))); 125 | /* The alignment might seem pointless, but allegedly CRIS needs it */ 126 | 127 | struct rb_root 128 | { 129 | struct rb_node *rb_node; 130 | }; 131 | 132 | 133 | #define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) 134 | #define rb_color(r) ((r)->rb_parent_color & 1) 135 | #define rb_is_red(r) (!rb_color(r)) 136 | #define rb_is_black(r) rb_color(r) 137 | #define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) 138 | #define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) 139 | 140 | static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) 141 | { 142 | rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; 143 | } 144 | static inline void rb_set_color(struct rb_node *rb, int color) 145 | { 146 | rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 147 | } 148 | 149 | #define RB_ROOT (struct rb_root) { NULL, } 150 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) 151 | 152 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) 153 | #define RB_EMPTY_NODE(node) (rb_parent(node) == node) 154 | #define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) 155 | 156 | static inline void rb_init_node(struct rb_node *rb) 157 | { 158 | rb->rb_parent_color = 0; 159 | rb->rb_right = NULL; 160 | rb->rb_left = NULL; 161 | RB_CLEAR_NODE(rb); 162 | } 163 | 164 | extern void rb_insert_color(struct rb_node *, struct rb_root *); 165 | extern void rb_erase(struct rb_node *, struct rb_root *); 166 | 167 | typedef void (*rb_augment_f)(struct rb_node *node, void *data); 168 | 169 | extern void rb_augment_insert(struct rb_node *node, 170 | rb_augment_f func, void *data); 171 | extern struct rb_node *rb_augment_erase_begin(struct rb_node *node); 172 | extern void rb_augment_erase_end(struct rb_node *node, 173 | rb_augment_f func, void *data); 174 | 175 | /* Find logical next and previous nodes in a tree */ 176 | extern struct rb_node *rb_next(const struct rb_node *); 177 | extern struct rb_node *rb_prev(const struct rb_node *); 178 | extern struct rb_node *rb_first(const struct rb_root *); 179 | extern struct rb_node *rb_last(const struct rb_root *); 180 | 181 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ 182 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 183 | struct rb_root *root); 184 | 185 | static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, 186 | struct rb_node ** rb_link) 187 | { 188 | node->rb_parent_color = (unsigned long )parent; 189 | node->rb_left = node->rb_right = NULL; 190 | 191 | *rb_link = node; 192 | } 193 | 194 | #endif /* _LINUX_RBTREE_H */ 195 | 196 | -------------------------------------------------------------------------------- /test_map.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 zkdnfcf, Inc. All Rights Reserved 4 | * $Id$ 5 | * 6 | **************************************************************************/ 7 | 8 | /** 9 | * @file test_map.c 10 | * @author zk(tjbroadroad@163.com) 11 | * @date 2016/06/01 09:38:32 12 | * @version $Revision$ 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "rbtree.h" 18 | #include "map.h" 19 | #include 20 | #include 21 | 22 | root_t tree = RB_ROOT; 23 | 24 | int main() { 25 | char *key = "hello"; 26 | char *word = "world"; 27 | put(&tree, key, word); 28 | 29 | char *key1 = "hello 1"; 30 | char *word1 = "world 1"; 31 | put(&tree, key1, word1); 32 | 33 | 34 | char *key2 = "hello 1"; 35 | char *word2 = "world 2 change"; 36 | put(&tree, key2, word2); 37 | 38 | map_t *data1 = get(&tree, "hello 1"); 39 | 40 | if (data1 != NULL) 41 | printf("%s\n", data1->val); 42 | 43 | map_t *node; 44 | for (node = map_first(&tree); node; node=map_next(&(node->node))) { 45 | printf("%s\n", node->key); 46 | } 47 | 48 | // free map if you don't need 49 | map_t *nodeFree = NULL; 50 | for (nodeFree = map_first(&tree); nodeFree; nodeFree = map_first(&tree)) { 51 | if (nodeFree) { 52 | rb_erase(&nodeFree->node, &tree); 53 | map_free(nodeFree); 54 | } 55 | } 56 | return 0; 57 | } 58 | 59 | /* vim: set ts=4 sw=4 sts=4 tw=100 */ 60 | --------------------------------------------------------------------------------