src/rbtree.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

Include dependency graph for rbtree.c:

Go to the source code of this file.

Data Structures

struct  rbtree_node_t
struct  rbtree_head_t

Defines

#define NODE_RED   0
#define NODE_BLACK   1
#define SEARCH_EQUAL   0x1
#define SEARCH_GTEQ   0x2
#define SEARCH_LTEQ   0x3
#define SEARCH_GT   0x4
#define SEARCH_LT   0x5
#define SEARCH_NEXT   0x6
#define SEARCH_PREV   0x7
#define SEARCH_FIRST   0x8
#define SEARCH_LAST   0x9
#define WALK_PREORDER   0x100
#define WALK_INORDER   0x101
#define WALK_POSTORDER   0x102
#define rbann(format, args...)   printf("%d: " format "\n", __LINE__, ##args)
#define rbfail(format, args...)   do { printf("%d: " format "\n", __LINE__, ##args); abort(); } while (0)

Typedefs

typedef rbtree_node_t rbtree_node
typedef rbtree_head_trbtree

Functions

rbtree rb_init (int(*)(void *, void *, void *), void *)
void rb_destroy (rbtree)
void rb_insert (rbtree, void *key, void *data)
void * rb_find (rbtree, void *key)
int rb_exists (rbtree, void *key)
void * rb_delete (rbtree, void *key)
void rb_walk (rbtree, int, int(*)(void *, void *, int, void *), void *)
unsigned int rb_size (rbtree)
void * rb_search (rbtree, int, void *)
static rbtree_noderb_find_minimum (rbtree_node *node)
static rbtree_noderb_find_maximum (rbtree_node *node)
static rbtree_noderb_find_successor_node (rbtree_node *node)
static rbtree_noderb_find_predecessor_node (rbtree_node *node)
void rb_release (rbtree bt, void(*release)(void *, void *, void *), void *arg)
static rbtree_noderb_allocate (rbtree_node *parent, void *key, void *data)
static void rb_rotate_right (rbtree bt, rbtree_node *pivot)
static void rb_rotate_left (rbtree bt, rbtree_node *pivot)
static void rb_unlink_leaf (rbtree bt, rbtree_node *leaf)
void * rb_index (rbtree bt, int index)


Define Documentation

#define NODE_BLACK   1

Definition at line 28 of file rbtree.c.

Referenced by rb_insert(), and rb_unlink_leaf().

#define NODE_RED   0

Definition at line 27 of file rbtree.c.

Referenced by rb_insert(), and rb_unlink_leaf().

#define rbann ( format,
args...   )     printf("%d: " format "\n", __LINE__, ##args)

Definition at line 478 of file rbtree.c.

#define rbfail ( format,
args...   )     do { printf("%d: " format "\n", __LINE__, ##args); abort(); } while (0)

Definition at line 479 of file rbtree.c.

Referenced by rb_index(), and rb_unlink_leaf().

#define SEARCH_EQUAL   0x1

Definition at line 30 of file rbtree.c.

Referenced by rb_search().

#define SEARCH_FIRST   0x8

Definition at line 37 of file rbtree.c.

Referenced by auto_astar_generate_path(), do_destroychannel(), hash_firstentry(), hash_firstkey(), and rb_search().

#define SEARCH_GT   0x4

Definition at line 33 of file rbtree.c.

Referenced by hash_nextentry(), and rb_search().

#define SEARCH_GTEQ   0x2

Definition at line 31 of file rbtree.c.

Referenced by rb_search().

#define SEARCH_LAST   0x9

Definition at line 38 of file rbtree.c.

Referenced by auto_gun_event(), and rb_search().

#define SEARCH_LT   0x5

Definition at line 34 of file rbtree.c.

Referenced by rb_search().

#define SEARCH_LTEQ   0x3

Definition at line 32 of file rbtree.c.

Referenced by rb_search().

#define SEARCH_NEXT   0x6

Definition at line 35 of file rbtree.c.

Referenced by hash_nextkey(), and rb_search().

#define SEARCH_PREV   0x7

Definition at line 36 of file rbtree.c.

Referenced by rb_search().

#define WALK_INORDER   0x101

Definition at line 41 of file rbtree.c.

Referenced by auto_gun_event(), cque_dump_restart(), hashreplall(), logcache_destruct(), logcache_list(), mmdb_db_write(), and rb_walk().

#define WALK_POSTORDER   0x102

Definition at line 42 of file rbtree.c.

Referenced by hashflush(), and rb_walk().

#define WALK_PREORDER   0x100

Definition at line 40 of file rbtree.c.

Referenced by rb_walk().


Typedef Documentation

typedef struct rbtree_head_t * rbtree

typedef struct rbtree_node_t rbtree_node


Function Documentation

static rbtree_node* rb_allocate ( rbtree_node parent,
void *  key,
void *  data 
) [static]

Definition at line 218 of file rbtree.c.

References rbtree_node_t::count, rbtree_node_t::data, rbtree_node_t::key, and rbtree_node_t::parent.

Referenced by rb_insert().

00219 {
00220     rbtree_node *temp;
00221     temp = malloc(sizeof(struct rbtree_node_t));
00222     memset(temp, 0, sizeof(struct rbtree_node_t));
00223     temp->parent = parent;
00224     temp->key = key;
00225     temp->data = data;
00226     temp->count = 1;
00227     return temp;
00228 }

void * rb_delete ( rbtree  ,
void *  key 
)

Definition at line 660 of file rbtree.c.

References rbtree_head_t::compare_function, rbtree_node_t::count, rbtree_node_t::data, rbtree_head_t::head, rbtree_node_t::key, rbtree_node_t::left, rb_find_successor_node(), rb_unlink_leaf(), rbtree_node_t::right, rbtree_head_t::size, and rbtree_head_t::token.

Referenced by auto_astar_generate_path(), comstar_remove_user_from_channel(), desc_delhash(), do_destroychannel(), hashdelete(), logcache_close(), nhashdelete(), and pcache_trim().

00661 {
00662     rbtree_node *node = NULL, *child = NULL, *tail;
00663     void *data;
00664     int compare_result;
00665 
00666     if(!bt->head) {
00667         return NULL;
00668     }
00669 
00670     node = bt->head;
00671     while (node != NULL) {
00672         compare_result = (*bt->compare_function) (key, node->key, bt->token);
00673         if(compare_result == 0) {
00674             break;
00675         } else if(compare_result < 0) {
00676             if(node->left != NULL) {
00677                 node = node->left;
00678             } else {
00679                 return NULL;
00680             }
00681         } else {
00682             if(node->right != NULL) {
00683                 node = node->right;
00684             } else {
00685                 return NULL;
00686             }
00687         }
00688     }
00689 
00690     if(node == NULL) {
00691         return node;
00692     }
00693 
00694     data = node->data;
00695     bt->size--;
00696 
00697     // XXX: handle deleting the head.
00698 
00699     if(node == bt->head && node->left == NULL && node->right == NULL) {
00700         bt->head = NULL;
00701         free(node);
00702         return data;
00703     }
00704 
00705     /* 
00706      * PROPERTY 3 OF RED BLACK TREES STATES:
00707      * 
00708      * Any two paths from a given node v down to a leaf node contain
00709      * the same number of black nodes.
00710      *
00711      * MEANING:
00712      * That all paths to all leaf nodes should contain the same
00713      * number of black nodes. Thus, we need to handle deleting a
00714      * black node in every situation, even if it is a leaf.
00715      */
00716 
00717     // our child has at most one child (or none.)
00718     if(node->left == NULL || node->right == NULL) {
00719         tail = node;
00720         while (tail) {
00721             tail->count--;
00722             tail = tail->parent;
00723         }
00724         rb_unlink_leaf(bt, node);
00725         free(node);
00726         return data;
00727     }
00728     // If we have full children, then we're guaranteed a successor
00729     // without empty children.
00730 
00731     child = rb_find_successor_node(node);
00732     tail = child;
00733     while (tail) {
00734         tail->count--;
00735         tail = tail->parent;
00736     }
00737     rb_unlink_leaf(bt, child);
00738 
00739     node->data = child->data;
00740     node->key = child->key;
00741 
00742     // XXX: finish delete
00743 
00744     free(child);
00745     return data;
00746 }

void rb_destroy ( rbtree   ) 

Definition at line 186 of file rbtree.c.

References rbtree_head_t::head, rbtree_node_t::left, rbtree_node_t::parent, and rbtree_node_t::right.

Referenced by auto_astar_generate_path(), auto_gun_event(), auto_newautopilot(), auto_update_profile_event(), hashflush(), logcache_destruct(), newfreemech(), and nhashflush().

00187 {
00188     rbtree_node *node, *parent;
00189     node = bt->head;
00190 
00191     if(bt->head) {
00192         while (node != NULL) {
00193             if(node->left != NULL) {
00194                 node = node->left;
00195                 continue;
00196             } else if(node->right != NULL) {
00197                 node = node->right;
00198                 continue;
00199             } else {
00200                 parent = node->parent;
00201                 if(parent && parent->left == node)
00202                     parent->left = NULL;
00203                 else if(parent && parent->right == node)
00204                     parent->right = NULL;
00205                 else if(parent) {
00206                     fprintf(stderr, "serious braindamage.\n");
00207                     exit(1);
00208                 }
00209                 free(node);
00210                 node = parent;
00211             }
00212         }
00213     }
00214     free(bt);
00215     return;
00216 }

int rb_exists ( rbtree  ,
void *  key 
)

Definition at line 446 of file rbtree.c.

References rbtree_head_t::compare_function, rbtree_head_t::head, rbtree_node_t::key, rbtree_node_t::left, rbtree_node_t::right, and rbtree_head_t::token.

Referenced by auto_astar_generate_path(), auto_gun_event(), comstar_add_user_to_channel(), comstar_find_channel_by_user_alias(), hashadd(), hashdelete(), logcache_open(), and nhashadd().

00447 {
00448     rbtree_node *node;
00449     int compare_result;
00450     if(!bt->head) {
00451         return 0;
00452     }
00453     node = bt->head;
00454     while (node != NULL) {
00455         compare_result = (*bt->compare_function) (key, node->key, bt->token);
00456         if(compare_result == 0) {
00457             return 1;
00458         } else if(compare_result < 0) {
00459             // Go Left
00460             if(node->left != NULL) {
00461                 node = node->left;
00462             } else {
00463                 return 0;
00464             }
00465         } else {
00466             if(node->right != NULL) {
00467                 node = node->right;
00468             } else {
00469                 return 0;
00470             }
00471         }
00472     }
00473     /* Shouldn't happen. */
00474     fprintf(stderr, "Serious fault in rbtree.c:rb_exists!\n");
00475     exit(1);
00476 }

void * rb_find ( rbtree  ,
void *  key 
)

Definition at line 413 of file rbtree.c.

References rbtree_head_t::compare_function, rbtree_node_t::data, rbtree_head_t::head, rbtree_node_t::key, rbtree_node_t::left, rbtree_node_t::right, and rbtree_head_t::token.

Referenced by auto_astar_generate_path(), comstar_find_channel_by_name(), comstar_find_channel_by_user_alias(), comstar_find_user_channels(), comstar_remove_user_from_channel(), cque_find(), desc_addhash(), desc_delhash(), do_quitprog(), handle_prog(), hashfind(), hashrepl(), logcache_writelog(), nhashfind(), and pcache_find().

00414 {
00415     rbtree_node *node;
00416     int compare_result;
00417 
00418     if(!bt->head) {
00419         return NULL;
00420     }
00421     node = bt->head;
00422     while (node != NULL) {
00423         compare_result = (*bt->compare_function) (key, node->key, bt->token);
00424         if(compare_result == 0) {
00425             return node->data;
00426         } else if(compare_result < 0) {
00427             // Go Left
00428             if(node->left != NULL) {
00429                 node = node->left;
00430             } else {
00431                 return NULL;
00432             }
00433         } else {
00434             if(node->right != NULL) {
00435                 node = node->right;
00436             } else {
00437                 return NULL;
00438             }
00439         }
00440     }
00441     /* Shouldn't happen. */
00442     fprintf(stderr, "Serious fault in rbtree.c:rb_find!\n");
00443     exit(1);
00444 }

static rbtree_node* rb_find_maximum ( rbtree_node node  )  [static]

Definition at line 96 of file rbtree.c.

References rbtree_node_t::right.

Referenced by rb_search().

00097 {
00098     rbtree_node *child;
00099     child = node;
00100     if(!node)
00101         return NULL;
00102     while (child->right != NULL)
00103         child = child->right;
00104     return child;
00105 }

static rbtree_node* rb_find_minimum ( rbtree_node node  )  [static]

Definition at line 85 of file rbtree.c.

References rbtree_node_t::left.

Referenced by rb_search().

00086 {
00087     rbtree_node *child;
00088     child = node;
00089     if(!node)
00090         return NULL;
00091     while (child->left != NULL)
00092         child = child->left;
00093     return child;
00094 }

static rbtree_node* rb_find_predecessor_node ( rbtree_node node  )  [static]

Definition at line 130 of file rbtree.c.

References rbtree_node_t::left, rbtree_node_t::parent, and rbtree_node_t::right.

Referenced by rb_search().

00131 {
00132     rbtree_node *child, *parent;
00133     if(!node)
00134         return NULL;
00135     if(node->left != NULL) {
00136         child = node->left;
00137         while (child->right != NULL)
00138             child = child->right;
00139         return child;
00140     } else {
00141         child = node;
00142         parent = node->parent;
00143         while (parent != NULL && child == parent->left) {
00144             child = parent;
00145             parent = parent->parent;
00146         }
00147         return parent;
00148     }
00149     return NULL;
00150 }

static rbtree_node* rb_find_successor_node ( rbtree_node node  )  [static]

Definition at line 107 of file rbtree.c.

References rbtree_node_t::left, rbtree_node_t::parent, and rbtree_node_t::right.

Referenced by rb_delete(), and rb_search().

00108 {
00109     rbtree_node *child, *parent;
00110     if(!node)
00111         return NULL;
00112     if(node->right != NULL) {
00113         child = node->right;
00114         while (child->left != NULL) {
00115             child = child->left;
00116         }
00117         return child;
00118     } else {
00119         child = node;
00120         parent = node->parent;
00121         while (parent != NULL && child == parent->right) {
00122             child = parent;
00123             parent = child->parent;
00124         }
00125         return parent;
00126     }
00127     return NULL;
00128 }

void* rb_index ( rbtree  bt,
int  index 
)

Definition at line 895 of file rbtree.c.

References rbtree_node_t::count, rbtree_node_t::data, rbtree_head_t::head, rbtree_node_t::left, rbfail, and rbtree_node_t::right.

00896 {
00897     rbtree_node *iter;
00898     int leftcount;
00899     iter = bt->head;
00900 
00901     while (iter) {
00902         leftcount = (iter->left ? iter->left->count : 0);
00903 
00904         if(index == leftcount) {
00905             return iter->data;
00906         }
00907         if(index < leftcount) {
00908             iter = iter->left;
00909         } else {
00910             index -= leftcount + 1;
00911             iter = iter->right;
00912         }
00913     }
00914     rbfail("major braindamage.");
00915 }

rbtree rb_init ( int(*)(void *, void *, void *)  ,
void *   
)

Definition at line 71 of file rbtree.c.

References rbtree_head_t::compare_function, rbtree_head_t::size, and rbtree_head_t::token.

Referenced by auto_astar_generate_path(), auto_gun_event(), comstar_find_user_channels(), comstar_init(), cque_init(), do_createchannel(), hashflush(), hashinit(), logcache_init(), main(), nhashflush(), nhashinit(), and pcache_init().

00072 {
00073     rbtree temp;
00074 
00075     temp = malloc(sizeof(struct rbtree_head_t));
00076     if(temp == NULL)
00077         return NULL;
00078     memset(temp, 0, sizeof(struct rbtree_head_t));
00079     temp->compare_function = compare_function;
00080     temp->token = token;
00081     temp->size = 0;
00082     return temp;
00083 }

void rb_insert ( rbtree  ,
void *  key,
void *  data 
)

Definition at line 288 of file rbtree.c.

References rbtree_node_t::color, rbtree_head_t::compare_function, rbtree_node_t::count, rbtree_node_t::data, rbtree_head_t::head, rbtree_node_t::key, rbtree_node_t::left, NODE_BLACK, NODE_RED, rbtree_node_t::parent, rb_allocate(), rb_rotate_left(), rb_rotate_right(), rbtree_node_t::right, rbtree_head_t::size, and rbtree_head_t::token.

Referenced by auto_astar_generate_path(), auto_gun_event(), comstar_add_user_to_channel(), comstar_find_user_channels(), cque_find(), desc_addhash(), desc_delhash(), hashadd(), logcache_open(), nhashadd(), nhashrepl(), and pcache_find().

00289 {
00290     rbtree_node *node;
00291     rbtree_node *iter;
00292     int compare_result;
00293 
00294     if(!bt->head) {
00295         bt->head = rb_allocate(NULL, key, data);
00296         bt->size++;
00297         bt->head->color = NODE_BLACK;
00298         return;
00299     }
00300 
00301     node = bt->head;
00302     while (node != NULL) {
00303         compare_result = (*bt->compare_function) (key, node->key, bt->token);
00304         if(compare_result == 0) {
00305             // Key already exists, replace data.
00306             node->key = key;
00307             node->data = data;
00308             return;
00309         } else if(compare_result < 0) {
00310             // Go Left
00311             if(node->left != NULL) {
00312                 node = node->left;
00313             } else {
00314                 node->left = rb_allocate(node, key, data);
00315                 bt->size++;
00316                 node = node->left;
00317                 break;
00318             }
00319         } else {
00320             if(node->right != NULL) {
00321                 node = node->right;
00322             } else {
00323                 node->right = rb_allocate(node, key, data);
00324                 bt->size++;
00325                 node = node->right;
00326                 break;
00327             }
00328         }
00329     }
00330 
00331     iter = node->parent;
00332     while (iter) {
00333         iter->count++;
00334         iter = iter->parent;
00335     }
00336 
00337     node->color = NODE_RED;
00338     if(node->parent && node->parent->color == NODE_RED) {
00339         iter = node;
00340         while (iter != bt->head && iter->parent->parent
00341                 && iter->parent->color == NODE_RED) {
00342             bt->head->color = NODE_BLACK;
00343             if(iter->parent == iter->parent->parent->left) {
00344                 // parent is left child of grandparent
00345                 if(iter->parent->parent->right != NULL &&
00346                         iter->parent->parent->right->color == NODE_RED) {
00347                     // Case 1:
00348                     // The current node has a red uncle and it's parent is parent node is a 
00349                     // red left child. 
00350                     iter->parent->color = NODE_BLACK;
00351                     iter->parent->parent->color = NODE_RED;
00352                     if(iter->parent->parent->right)
00353                         iter->parent->parent->right->color = NODE_BLACK;
00354                     iter = iter->parent->parent;
00355                     continue;
00356                 } else {
00357                     // Case 2 or 3:
00358                     // The current node has a black uncle.
00359                     if(iter->parent->right == iter) {
00360                         // Case 2:
00361                         // The current node has a black uncle and is the right child
00362                         // of the parent. The parent is the red left child. The parent's
00363                         // sibling, the current node's uncle, is black.
00364                         rb_rotate_left(bt, iter->parent);
00365                         iter = iter->left;
00366                     }
00367                     // Case 3:
00368                     // The current node is a left child. It's parent is a red left child
00369                     // and has a black sibling. 
00370                     iter->parent->color = NODE_BLACK;
00371                     iter->parent->parent->color = NODE_RED;
00372                     rb_rotate_right(bt, iter->parent->parent);
00373                     break;
00374                 }
00375             } else {
00376                 // parent is right child of grandparent
00377                 if(iter->parent->parent->left != NULL &&
00378                         iter->parent->parent->left->color == NODE_RED) {
00379                     // Case 1:
00380                     // The current node has a red uncle and it's parent is parent node is a 
00381                     // red right child. 
00382                     iter->parent->color = NODE_BLACK;
00383                     iter->parent->parent->color = NODE_RED;
00384                     if(iter->parent->parent->left)
00385                         iter->parent->parent->left->color = NODE_BLACK;
00386                     iter = iter->parent->parent;
00387                     continue;
00388                 } else {
00389                     // Case 2 or 3:
00390                     // The current node has a black uncle.
00391                     if(iter->parent->left == iter) {
00392                         // Case 2:
00393                         // The current node has a black uncle and is the left child
00394                         // of the parent. The parent is the red right child. The parent's
00395                         // sibling, the current node's uncle, is black.
00396                         rb_rotate_right(bt, iter->parent);
00397                         iter = iter->right;
00398                     }
00399                     // Case 3:
00400                     // The current node is a right child. It's parent is a red right child
00401                     // and has a black sibling. 
00402                     iter->parent->color = NODE_BLACK;
00403                     iter->parent->parent->color = NODE_RED;
00404                     rb_rotate_left(bt, iter->parent->parent);
00405                     continue;
00406                 }
00407             }
00408         }
00409     }
00410     bt->head->color = NODE_BLACK;
00411 }

void rb_release ( rbtree  bt,
void(*)(void *, void *, void *)  release,
void *  arg 
)

Definition at line 152 of file rbtree.c.

References rbtree_node_t::data, rbtree_head_t::head, rbtree_node_t::key, rbtree_node_t::left, rbtree_node_t::parent, and rbtree_node_t::right.

Referenced by auto_astar_generate_path().

00154 {
00155     rbtree_node *node, *parent;
00156     node = bt->head;
00157 
00158     if(bt->head) {
00159         while (node != NULL) {
00160             if(node->left != NULL) {
00161                 node = node->left;
00162                 continue;
00163             } else if(node->right != NULL) {
00164                 node = node->right;
00165                 continue;
00166             } else {
00167                 parent = node->parent;
00168                 if(parent && parent->left == node)
00169                     parent->left = NULL;
00170                 else if(parent && parent->right == node)
00171                     parent->right = NULL;
00172                 else if(parent) {
00173                     fprintf(stderr, "serious braindamage.\n");
00174                     exit(1);
00175                 }
00176                 release(node->key, node->data, arg);
00177                 free(node);
00178                 node = parent;
00179             }
00180         }
00181     }
00182     free(bt);
00183     return;
00184 }

static void rb_rotate_left ( rbtree  bt,
rbtree_node pivot 
) [static]

Definition at line 259 of file rbtree.c.

References rbtree_node_t::count, rbtree_head_t::head, rbtree_node_t::left, rbtree_node_t::parent, and rbtree_node_t::right.

Referenced by rb_insert(), and rb_unlink_leaf().

00260 {
00261     rbtree_node *child;
00262 
00263     if(!pivot || !pivot->right)
00264         return;
00265     child = pivot->right;
00266 
00267     pivot->right = child->left;
00268     if(child->left != NULL)
00269         child->left->parent = pivot;
00270 
00271     child->parent = pivot->parent;
00272 
00273     if(pivot->parent) {
00274         if(pivot->parent->right == pivot)
00275             pivot->parent->right = child;
00276         else
00277             pivot->parent->left = child;
00278     } else
00279         bt->head = child;
00280     child->left = pivot;
00281     pivot->parent = child;
00282     child->count = pivot->count;
00283     pivot->count =
00284         1 + (pivot->left ? pivot->left->count : 0) +
00285         (pivot->right ? pivot->right->count : 0);
00286 }

static void rb_rotate_right ( rbtree  bt,
rbtree_node pivot 
) [static]

Definition at line 230 of file rbtree.c.

References rbtree_node_t::count, rbtree_head_t::head, rbtree_node_t::left, rbtree_node_t::parent, and rbtree_node_t::right.

Referenced by rb_insert(), and rb_unlink_leaf().

00231 {
00232     rbtree_node *child;
00233 
00234     if(!pivot || !pivot->left)
00235         return;
00236     child = pivot->left;
00237 
00238     pivot->left = child->right;
00239     if(child->right != NULL)
00240         child->right->parent = pivot;
00241 
00242     child->parent = pivot->parent;
00243 
00244     if(pivot->parent) {
00245         if(pivot->parent->left == pivot)
00246             pivot->parent->left = child;
00247         else
00248             pivot->parent->right = child;
00249     } else
00250         bt->head = child;
00251     child->right = pivot;
00252     pivot->parent = child;
00253     child->count = pivot->count;
00254     pivot->count =
00255         1 + (pivot->left ? pivot->left->count : 0) +
00256         (pivot->right ? pivot->right->count : 0);
00257 }

void * rb_search ( rbtree  ,
int  ,
void *   
)

Definition at line 794 of file rbtree.c.

References rbtree_head_t::compare_function, rbtree_node_t::data, rbtree_head_t::head, rbtree_node_t::key, rbtree_node_t::left, rb_find_maximum(), rb_find_minimum(), rb_find_predecessor_node(), rb_find_successor_node(), rbtree_node_t::right, SEARCH_EQUAL, SEARCH_FIRST, SEARCH_GT, SEARCH_GTEQ, SEARCH_LAST, SEARCH_LT, SEARCH_LTEQ, SEARCH_NEXT, SEARCH_PREV, and rbtree_head_t::token.

Referenced by auto_astar_generate_path(), auto_gun_event(), do_destroychannel(), hash_firstentry(), hash_firstkey(), hash_nextentry(), and hash_nextkey().

00795 {
00796     rbtree_node *node, *last;
00797     int compare_result;
00798     int found = 0;
00799 
00800     if(!bt->head) {
00801         return NULL;
00802     }
00803 
00804     if(method == SEARCH_FIRST) {
00805         node = rb_find_minimum(bt->head);
00806         return node->data;
00807     } else if(method == SEARCH_LAST) {
00808         node = rb_find_maximum(bt->head);
00809         return node->data;
00810     }
00811 
00812     node = bt->head;
00813     while (node != NULL) {
00814         last = node;
00815         compare_result = (*bt->compare_function) (key, node->key, bt->token);
00816         if(compare_result == 0) {
00817             found = 1;
00818             break;
00819         } else if(compare_result < 0) {
00820             // Go Left
00821             if(node->left != NULL) {
00822                 node = node->left;
00823             } else {
00824                 node = NULL;
00825                 break;
00826             }
00827         } else {
00828             if(node->right != NULL) {
00829                 node = node->right;
00830             } else {
00831                 node = NULL;
00832                 break;
00833             }
00834         }
00835     }
00836 
00837     if(found
00838             && (method == SEARCH_EQUAL || method == SEARCH_LTEQ
00839                 || method == SEARCH_GTEQ)) {
00840         if(node)
00841             return node->data;
00842         else
00843             return NULL;
00844     }
00845 
00846     if(!found
00847             && (method == SEARCH_EQUAL || method == SEARCH_NEXT
00848                 || method == SEARCH_PREV)) {
00849         return NULL;
00850     }
00851 
00852     if(method == SEARCH_GTEQ || (!found && method == SEARCH_GT)) {
00853         if(compare_result > 0) {
00854             node = rb_find_successor_node(last);
00855             if(node)
00856                 return node->data;
00857             else
00858                 return node;
00859         } else {
00860             if(last)
00861                 return last->data;
00862             else
00863                 return last;
00864         }
00865     }
00866 
00867     if(method == SEARCH_LTEQ || (!found && method == SEARCH_LT)) {
00868         if(compare_result < 0) {
00869             node = rb_find_predecessor_node(last);
00870             return node->data;
00871         } else {
00872             return last->data;
00873         }
00874     }
00875 
00876     if(method == SEARCH_NEXT || (found && method == SEARCH_GT)) {
00877         node = rb_find_successor_node(node);
00878         if(node)
00879             return node->data;
00880         else
00881             return node;
00882     }
00883 
00884     if(method == SEARCH_PREV || (found && method == SEARCH_LT)) {
00885         node = rb_find_predecessor_node(node);
00886         if(node)
00887             return node->data;
00888         else
00889             return node;
00890     }
00891 
00892     return NULL;
00893 }

unsigned int rb_size ( rbtree   ) 

Definition at line 789 of file rbtree.c.

References rbtree_head_t::size.

Referenced by auto_astar_generate_path(), auto_gun_event(), cque_dump_restart(), do_destroychannel(), hashinfo(), logcache_list(), and mmdb_db_write().

00790 {
00791     return bt->size;
00792 }

static void rb_unlink_leaf ( rbtree  bt,
rbtree_node leaf 
) [static]

Definition at line 481 of file rbtree.c.

References rbtree_node_t::color, rbtree_head_t::head, rbtree_node_t::left, NODE_BLACK, NODE_RED, rbtree_node_t::parent, rb_rotate_left(), rb_rotate_right(), rbfail, and rbtree_node_t::right.

Referenced by rb_delete().

00482 {
00483     rbtree_node *sibling = NULL, *node;
00484 
00485     node = leaf;
00486 
00487     if(node->color == NODE_RED) {
00488         // if node is red and has at most one child, then it has no child.
00489         if(node->parent->left == node) {
00490             node->parent->left = NULL;
00491         } else {
00492             node->parent->right = NULL;
00493         }
00494         node->parent = NULL;
00495         return;
00496     }
00497     // node is black so it has only one red child, two black children, or no children.
00498     // If it had two children, we would've handled that in rb_delete()
00499     if(node->left) {
00500         if(node == bt->head) {
00501             bt->head = node->left;
00502             node->left->parent = NULL;
00503         } else if(node->parent->left == node) {
00504             node->parent->left = node->left;
00505             node->left->parent = node->parent;
00506         } else {
00507             node->parent->right = node->left;
00508             node->left->parent = node->parent;
00509         }
00510         if(node->color == NODE_BLACK) {
00511             if(node->left->color == NODE_RED) {
00512                 node->left->color = NODE_BLACK;
00513             } else {
00514                 rbfail("shit.");
00515             }
00516         }
00517         node->parent = NULL;
00518         node->left = NULL;
00519         return;
00520     }
00521 
00522     if(node->right) {
00523         if(node == bt->head) {
00524             bt->head = node->right;
00525             node->right->parent = NULL;
00526         } else if(node->parent->right == node) {
00527             node->parent->right = node->right;
00528             node->right->parent = node->parent;
00529         } else {
00530             node->parent->left = node->right;
00531             node->right->parent = node->parent;
00532         }
00533         if(node->color == NODE_BLACK) {
00534             if(node->right->color == NODE_RED) {
00535                 node->right->color = NODE_BLACK;
00536             } else {
00537                 rbfail("shit.");
00538             }
00539         }
00540         node->right = NULL;
00541         node->left = NULL;
00542         return;
00543     }
00544     // node is black and has no children, if it had two children, then rb_delete
00545     // would have handled the situation. Since the node is black and has no
00546     // children, things get complicated.
00547 
00548     while (node != bt->head) {
00549         // First we loop through the Case 2a situations.
00550         // 
00551         if(node->parent->left == node) {
00552             sibling = node->parent->right;
00553         } else {
00554             sibling = node->parent->left;
00555         }
00556         // if the parent is black, it has two black children, or no children.
00557         // since we are a child, we're guaranteed a sibling.
00558         if(!sibling)                    // Sanity Check
00559             rbfail
00560                 ("serious braindamage: black child of black parent has no sibling.");
00561         if(node->parent->color == NODE_BLACK && sibling->color == NODE_BLACK
00562                 && (!sibling->right || sibling->right->color == NODE_BLACK)
00563                 && (!sibling->left || sibling->left->color == NODE_BLACK)) {
00564             sibling->color = NODE_RED;
00565             node = node->parent;
00566             continue;
00567         }
00568         break;
00569     }
00570 
00571     if(node == bt->head) {
00572         node->color = NODE_BLACK;
00573         goto done;
00574     }
00575 
00576     if(node->parent->left == node) {
00577         sibling = node->parent->right;
00578     } else {
00579         sibling = node->parent->left;
00580     }
00581 
00582     if(node->parent->color == NODE_BLACK && sibling && 
00583             sibling->color == NODE_RED && 
00584             (!sibling->right || sibling->right->color == NODE_BLACK) && 
00585             (!sibling->left || sibling->left-> color == NODE_BLACK)) {
00586         node->parent->color = NODE_RED;
00587         sibling->color = NODE_BLACK;
00588         if(node->parent->left == node) {
00589             rb_rotate_left(bt, node->parent);
00590             sibling = node->parent->right;
00591         } else {
00592             rb_rotate_right(bt, node->parent);
00593             sibling = node->parent->left;
00594         }
00595     }
00596 
00597     if(!sibling && node->parent->color == NODE_RED) {
00598         node->parent->color = NODE_BLACK;
00599         goto done;
00600     }
00601 
00602     if(node->parent->color == NODE_RED && sibling->color == NODE_BLACK &&
00603             (!sibling->right || sibling->right->color == NODE_BLACK) &&
00604             (!sibling->left || sibling->left->color == NODE_BLACK)) {
00605 
00606         sibling->color = NODE_RED;
00607         node->parent->color = NODE_BLACK;
00608         goto done;
00609     }
00610 
00611     if(node->parent->left == node) {
00612 
00613         if(sibling->color == NODE_BLACK &&
00614                 (sibling->left && sibling->left->color == NODE_RED) &&
00615                 (!sibling->right || sibling->right->color == NODE_BLACK)) {
00616             sibling->color = NODE_RED;
00617             sibling->left->color = NODE_BLACK;
00618             rb_rotate_right(bt, sibling);
00619             sibling = sibling->parent;
00620         }
00621 
00622         if(sibling->color == NODE_BLACK &&
00623                 (sibling->right && sibling->right->color == NODE_RED)) {
00624             sibling->right->color = NODE_BLACK;
00625             sibling->color = sibling->parent->color;
00626             sibling->parent->color = NODE_BLACK;
00627             rb_rotate_left(bt, sibling->parent);
00628         }
00629     } else {
00630 
00631         if(sibling->color == NODE_BLACK &&
00632                 (sibling->right && sibling->right->color == NODE_RED) &&
00633                 (!sibling->left || sibling->left->color == NODE_BLACK)) {
00634             sibling->color = NODE_RED;
00635             sibling->right->color = NODE_BLACK;
00636             rb_rotate_left(bt, sibling);
00637             sibling = sibling->parent;
00638         }
00639 
00640         if(sibling->color == NODE_BLACK &&
00641                 (sibling->left && sibling->left->color == NODE_RED)) {
00642             sibling->left->color = NODE_BLACK;
00643             sibling->color = sibling->parent->color;
00644             sibling->parent->color = NODE_BLACK;
00645             rb_rotate_right(bt, sibling->parent);
00646         }
00647     }
00648 
00649 done:
00650     if(leaf->parent->left == leaf) {
00651         leaf->parent->left = NULL;
00652     } else if(leaf->parent->right == leaf) {
00653         leaf->parent->right = NULL;
00654     } else {
00655         rbfail("major braindamage.");
00656     }
00657     return;
00658 }

void rb_walk ( rbtree  ,
int  ,
int(*)(void *, void *, int, void *)  ,
void *   
)

Definition at line 748 of file rbtree.c.

References rbtree_node_t::data, rbtree_head_t::head, rbtree_node_t::key, rbtree_node_t::left, rbtree_node_t::parent, rbtree_node_t::right, WALK_INORDER, WALK_POSTORDER, and WALK_PREORDER.

Referenced by auto_gun_event(), cque_dump_restart(), hashflush(), hashreplall(), logcache_destruct(), logcache_list(), and mmdb_db_write().

00750 {
00751     rbtree_node *last, *node;
00752     int depth = 0;
00753     if(!bt->head)
00754         return;
00755     last = NULL;
00756     node = bt->head;
00757     while (node != NULL) {
00758         if(last == node->parent) {
00759             if(how == WALK_PREORDER)
00760                 if(!(*callback) (node->key, node->data, depth, arg))
00761                     return;
00762             if(node->left != NULL) {
00763                 depth++;
00764                 last = node;
00765                 node = node->left;
00766                 continue;
00767             }
00768         }
00769         if(last == node->left || (last == node->parent && node->left == NULL)) {
00770             if(how == WALK_INORDER)
00771                 if(!(*callback) (node->key, node->data, depth, arg))
00772                     return;
00773             if(node->right != NULL) {
00774                 depth++;
00775                 last = node;
00776                 node = node->right;
00777                 continue;
00778             }
00779         }
00780         if(how == WALK_POSTORDER)
00781             if(!(*callback) (node->key, node->data, depth, arg))
00782                 return;
00783         depth--;
00784         last = node;
00785         node = node->parent;
00786     }
00787 }


Generated on Mon May 28 04:25:47 2007 for BattletechMUX by  doxygen 1.4.7