| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
- * This file is part of clib library
- * Copyright (C) 2011 Avinash Dongre ( dongre.avinash@gmail.com )
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
- #include "c_lib.h"
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- #define rb_sentinel &pTree->sentinel
- static void debug_verify_properties(struct clib_rb*);
- static void debug_verify_property_1(struct clib_rb*,struct clib_rb_node*);
- static void debug_verify_property_2(struct clib_rb*,struct clib_rb_node*);
- static int debug_node_color(struct clib_rb*,struct clib_rb_node* n);
- static void debug_verify_property_4(struct clib_rb*,struct clib_rb_node*);
- static void debug_verify_property_5(struct clib_rb*,struct clib_rb_node*);
- static void debug_verify_property_5_helper(struct clib_rb*,struct clib_rb_node*,int,int*);
- static void
- pvt_left_rotate(struct clib_rb *pTree, struct clib_rb_node *x){
- struct clib_rb_node *y;
- y = x->right;
- x->right = y->left;
- if (y->left != rb_sentinel)
- y->left->parent = x;
- if (y != rb_sentinel)
- y->parent = x->parent;
- if (x->parent){
- if (x == x->parent->left)
- x->parent->left = y;
- else
- x->parent->right = y;
- }
- else
- pTree->root = y;
- y->left = x;
- if (x != rb_sentinel)
- x->parent = y;
- }
- static void
- pvt_right_rotate(struct clib_rb *pTree, struct clib_rb_node *x) {
- struct clib_rb_node *y = x->left;
- x->left = y->right;
- if (y->right != rb_sentinel)
- y->right->parent = x;
- if (y != rb_sentinel)
- y->parent = x->parent;
- if (x->parent) {
- if (x == x->parent->right)
- x->parent->right = y;
- else
- x->parent->left = y;
- }
- else
- pTree->root = y;
- y->right = x;
- if (x != rb_sentinel)
- x->parent = y;
- }
- struct clib_rb*
- new_clib_rb(clib_compare fn_c,clib_destroy fn_ed, clib_destroy fn_vd ){
- struct clib_rb *pTree = (struct clib_rb*)malloc(sizeof(struct clib_rb));
- if ( pTree == (struct clib_rb*)0 )
- return (struct clib_rb*)0;
- pTree->compare_fn = fn_c;
- pTree->destruct_k_fn = fn_ed;
- pTree->destruct_v_fn = fn_vd;
- pTree->root = rb_sentinel;
- pTree->sentinel.left = rb_sentinel;
- pTree->sentinel.right = rb_sentinel;
- pTree->sentinel.parent = (struct clib_rb_node*)0 ;
- pTree->sentinel.color = clib_black;
- return pTree;
- }
- static void
- pvt_rb_insert_fixup( struct clib_rb *pTree, struct clib_rb_node *x ) {
- while (x != pTree->root && x->parent->color == clib_red) {
- if (x->parent == x->parent->parent->left) {
- struct clib_rb_node *y = x->parent->parent->right;
- if (y->color == clib_red) {
- x->parent->color = clib_black;
- y->color = clib_black;
- x->parent->parent->color = clib_red;
- x = x->parent->parent;
- } else {
- if (x == x->parent->right){
- x = x->parent;
- pvt_left_rotate (pTree, x);
- }
- x->parent->color = clib_black;
- x->parent->parent->color = clib_red;
- pvt_right_rotate (pTree, x->parent->parent);
- }
- } else {
- struct clib_rb_node *y = x->parent->parent->left;
- if (y->color == clib_red) {
- x->parent->color = clib_black;
- y->color = clib_black;
- x->parent->parent->color = clib_red;
- x = x->parent->parent;
- } else {
- if (x == x->parent->left) {
- x = x->parent;
- pvt_right_rotate (pTree, x);
- }
- x->parent->color = clib_black;
- x->parent->parent->color = clib_red;
- pvt_left_rotate (pTree, x->parent->parent);
- }
- }
- }
- pTree->root->color = clib_black;
- }
- struct clib_rb_node*
- find_clib_rb (struct clib_rb *pTree, void *key) {
- struct clib_rb_node *x = pTree->root;
- while (x != rb_sentinel) {
- int c = 0;
- void *cur_key ;
- get_raw_clib_object ( x->key, &cur_key );
- c = pTree->compare_fn (key, cur_key);
- free ( cur_key );
- if (c == 0) {
- break;
- } else {
- x = c < 0 ? x->left : x->right;
- }
- }
- if ( x == rb_sentinel )
- return (struct clib_rb_node*)0 ;
- return x;
- }
- clib_error
- insert_clib_rb(struct clib_rb *pTree, void *k, size_t key_size, void *v, size_t value_size) {
- clib_error rc = CLIB_ERROR_SUCCESS;
- struct clib_rb_node *x;
- struct clib_rb_node *y;
- struct clib_rb_node *z;
- x = (struct clib_rb_node*)malloc (sizeof(struct clib_rb_node));
- if ( x == (struct clib_rb_node*)0 )
- return CLIB_ERROR_MEMORY;
- x->left = rb_sentinel;
- x->right = rb_sentinel;
- x->color = clib_red;
- x->key = new_clib_object ( k, key_size );
- if ( v ) {
- x->value = new_clib_object ( v, value_size );
- } else {
- x->value = (struct clib_object*)0;
- }
- y = pTree->root;
- z = (struct clib_rb_node*)0 ;
- while (y != rb_sentinel) {
- int c = 0;
- void *cur_key;
- void* new_key;
- get_raw_clib_object ( y->key, &cur_key );
- get_raw_clib_object ( x->key, &new_key );
- c = (pTree->compare_fn) ( new_key , cur_key);
- free ( cur_key );
- free ( new_key );
- if (c == 0) {
- /* TODO : Delete node here */
- return CLIB_RBTREE_KEY_DUPLICATE;
- }
- z = y;
- if ( c < 0 )
- y = y->left;
- else
- y = y->right;
- }
- x->parent = z;
- if (z) {
- int c = 0;
- void *cur_key;
- void* new_key;
- get_raw_clib_object ( z->key, &cur_key );
- get_raw_clib_object ( x->key, &new_key );
- c = pTree->compare_fn( new_key, cur_key);
- free ( cur_key );
- free ( new_key );
- if (c < 0) {
- z->left = x;
- } else {
- z->right = x;
- }
- }
- else
- pTree->root = x;
- pvt_rb_insert_fixup (pTree, x);
- debug_verify_properties ( pTree);
- return rc;
- }
- static void
- pvt_rb_remove_fixup( struct clib_rb *pTree, struct clib_rb_node *x ) {
- while (x != pTree->root && x->color == clib_black) {
- if (x == x->parent->left) {
- struct clib_rb_node *w = x->parent->right;
- if (w->color == clib_red) {
- w->color = clib_black;
- x->parent->color = clib_red;
- pvt_left_rotate (pTree, x->parent);
- w = x->parent->right;
- }
- if (w->left->color == clib_black && w->right->color == clib_black) {
- w->color = clib_red;
- x = x->parent;
- } else {
- if (w->right->color == clib_black) {
- w->left->color = clib_black;
- w->color = clib_red;
- pvt_right_rotate (pTree, w);
- w = x->parent->right;
- }
- w->color = x->parent->color;
- x->parent->color = clib_black;
- w->right->color = clib_black;
- pvt_left_rotate (pTree, x->parent);
- x = pTree->root;
- }
- } else {
- struct clib_rb_node *w = x->parent->left;
- if (w->color == clib_red) {
- w->color = clib_black;
- x->parent->color = clib_red;
- pvt_right_rotate (pTree, x->parent);
- w = x->parent->left;
- }
- if (w->right->color == clib_black && w->left->color == clib_black) {
- w->color = clib_red;
- x = x->parent;
- } else {
- if (w->left->color == clib_black) {
- w->right->color = clib_black;
- w->color = clib_red;
- pvt_left_rotate (pTree, w);
- w = x->parent->left;
- }
- w->color = x->parent->color;
- x->parent->color = clib_black;
- w->left->color = clib_black;
- pvt_right_rotate (pTree, x->parent);
- x = pTree->root;
- }
- }
- }
- x->color = clib_black;
- }
- static struct clib_rb_node*
- pvt_remove_clib_rb(struct clib_rb *pTree, struct clib_rb_node *z ) {
- struct clib_rb_node *x = (struct clib_rb_node*)0 ;
- struct clib_rb_node *y = (struct clib_rb_node*)0 ;
- if (z->left == rb_sentinel || z->right == rb_sentinel)
- y = z;
- else {
- y = z->right;
- while (y->left != rb_sentinel)
- y = y->left;
- }
- if (y->left != rb_sentinel)
- x = y->left;
- else
- x = y->right;
- x->parent = y->parent;
- if (y->parent)
- {
- if (y == y->parent->left)
- y->parent->left = x;
- else
- y->parent->right = x;
- }
- else
- pTree->root = x;
- if (y != z) {
- struct clib_object* tmp;
- tmp = z->key;
- z->key = y->key;
- y->key = tmp;
- tmp = z->value;
- z->value = y->value;
- y->value = tmp;
- }
- if (y->color == clib_black)
- pvt_rb_remove_fixup (pTree, x);
- debug_verify_properties ( pTree);
- return y;
- }
- struct clib_rb_node*
- remove_clib_rb (struct clib_rb *pTree, void *key) {
- struct clib_rb_node *z = (struct clib_rb_node*)0 ;
- z = pTree->root;
- while (z != rb_sentinel) {
- int c = 0;
- void *cur_key;
- get_raw_clib_object ( z->key, &cur_key );
- c = pTree->compare_fn (key, cur_key);
- free ( cur_key );
- if ( c == 0) {
- break;
- }
- else {
- z = ( c < 0) ? z->left : z->right;
- }
- }
- if (z == rb_sentinel)
- return (struct clib_rb_node*)0 ;
- return pvt_remove_clib_rb(pTree, z );
- }
- static void
- pvt_delete_clib_rb_node (struct clib_rb *pTree, struct clib_rb_node *x ) {
- void *key;
- void *value;
- if ( pTree->destruct_k_fn ) {
- get_raw_clib_object ( x->key, &key );
- pTree->destruct_k_fn ( key );
- }
- delete_clib_object( x->key );
- if ( x->value ) {
- if ( pTree->destruct_v_fn ) {
- get_raw_clib_object ( x->value, &value);
- pTree->destruct_v_fn ( value );
- }
- delete_clib_object( x->value );
- }
- }
- clib_error
- delete_clib_rb(struct clib_rb *pTree) {
- clib_error rc = CLIB_ERROR_SUCCESS;
- struct clib_rb_node *z = pTree->root;
- while (z != rb_sentinel) {
- if (z->left != rb_sentinel)
- z = z->left;
- else if (z->right != rb_sentinel)
- z = z->right;
- else {
- pvt_delete_clib_rb_node ( pTree, z );
- if (z->parent) {
- z = z->parent;
- if (z->left != rb_sentinel){
- free ( z->left );
- z->left = rb_sentinel;
- }else if (z->right != rb_sentinel){
- free ( z->right );
- z->right = rb_sentinel;
- }
- } else {
- free ( z );
- z = rb_sentinel;
- }
- }
- }
- free ( pTree );
- return rc;
- }
- struct clib_rb_node *
- minimum_clib_rb( struct clib_rb *pTree, struct clib_rb_node *x ) {
- while ( x->left != rb_sentinel)
- x = x->left;
- return x;
- }
- struct clib_rb_node *
- maximum_clib_rb( struct clib_rb *pTree, struct clib_rb_node *x ) {
- while ( x->right != rb_sentinel)
- x = x->right;
- return x;
- }
- clib_bool
- empty_clib_rb(struct clib_rb *pTree) {
- if ( pTree->root != rb_sentinel )
- return clib_true;
- return clib_false;
- }
- struct clib_rb_node*
- tree_successor(struct clib_rb *pTree, struct clib_rb_node *x) {
- struct clib_rb_node *y = (struct clib_rb_node*)0;
- if ( x->right != rb_sentinel)
- return minimum_clib_rb( pTree, x->right);
-
- if ( x == maximum_clib_rb(pTree,pTree->root))
- return (struct clib_rb_node*)0;
- y = x->parent;
- while ( y != rb_sentinel && x == y->right ){
- x = y;
- y = y->parent;
- }
- return y;
- }
- void debug_verify_properties(struct clib_rb* t) {
- debug_verify_property_1(t,t->root);
- debug_verify_property_2(t,t->root);
- debug_verify_property_4(t,t->root);
- debug_verify_property_5(t,t->root);
- }
- void debug_verify_property_1(struct clib_rb *pTree,struct clib_rb_node* n) {
- assert(debug_node_color(pTree,n) == clib_red || debug_node_color(pTree,n) == clib_black);
- if (n == rb_sentinel) return;
- debug_verify_property_1(pTree,n->left);
- debug_verify_property_1(pTree,n->right);
- }
- void debug_verify_property_2(struct clib_rb *pTree,struct clib_rb_node* root) {
- assert(debug_node_color(pTree,root) == clib_black);
- }
- int debug_node_color(struct clib_rb *pTree,struct clib_rb_node* n) {
- return n == rb_sentinel ? clib_black : n->color;
- }
- void debug_verify_property_4(struct clib_rb *pTree,struct clib_rb_node* n) {
- if (debug_node_color(pTree,n) == clib_red) {
- assert (debug_node_color(pTree,n->left) == clib_black);
- assert (debug_node_color(pTree,n->right) == clib_black);
- assert (debug_node_color(pTree,n->parent) == clib_black);
- }
- if (n == rb_sentinel) return;
- debug_verify_property_4(pTree,n->left);
- debug_verify_property_4(pTree,n->right);
- }
- void debug_verify_property_5(struct clib_rb *pTree,struct clib_rb_node* root) {
- int black_count_path = -1;
- debug_verify_property_5_helper(pTree,root, 0, &black_count_path);
- }
- void debug_verify_property_5_helper(struct clib_rb *pTree,struct clib_rb_node* n, int black_count, int* path_black_count) {
- if (debug_node_color(pTree,n) == clib_black) {
- black_count++;
- }
- if (n == rb_sentinel) {
- if (*path_black_count == -1) {
- *path_black_count = black_count;
- } else {
- assert (black_count == *path_black_count);
- }
- return;
- }
- debug_verify_property_5_helper(pTree,n->left, black_count, path_black_count);
- debug_verify_property_5_helper(pTree,n->right, black_count, path_black_count);
- }
|