From: Fredrik Tolf Date: Sun, 24 Feb 2008 02:28:27 +0000 (+0100) Subject: Added bbtree functions. X-Git-Tag: 1.2~26 X-Git-Url: http://dolda2000.com/gitweb/?p=doldaconnect.git;a=commitdiff_plain;h=ffb8ed40b1aefe37a0f1d1b2d7c3bef9eb8e2cbc Added bbtree functions. --- diff --git a/common/utils.c b/common/utils.c index 49fb11b..701f162 100644 --- a/common/utils.c +++ b/common/utils.c @@ -891,3 +891,142 @@ wchar_t *wpfind(struct wcspair *list, wchar_t *key) } return(NULL); } + +static int btheight(struct btree *tree) +{ + if(tree == NULL) + return(0); + return(tree->h); +} + +static void btsetheight(struct btree *tree) +{ + int lh, rh; + + if(tree == NULL) + return; + lh = btheight(tree->l); + rh = btheight(tree->r); + tree->h = ((lh > rh)?lh:rh) + 1; +} + +static void bbtrl(struct btree **tree); + +static void bbtrr(struct btree **tree) +{ + struct btree *m, *l, *r; + + if(btheight((*tree)->l->r) > btheight((*tree)->l->l)) + bbtrl(&(*tree)->l); + r = (*tree); + l = r->l; + m = l->r; + r->l = m; + btsetheight(r); + l->r = r; + btsetheight(l); + *tree = l; +} + +static void bbtrl(struct btree **tree) +{ + struct btree *m, *l, *r; + + if(btheight((*tree)->r->l) > btheight((*tree)->r->r)) + bbtrr(&(*tree)->r); + l = (*tree); + r = l->r; + m = r->l; + l->r = m; + btsetheight(l); + r->l = l; + btsetheight(r); + *tree = r; +} + +int bbtreedel(struct btree **tree, void *item, int (*cmp)(void *, void *)) +{ + int c, r; + struct btree *s, **sp, *o; + + if(*tree == NULL) + return(0); + if((c = cmp(item, (*tree)->d)) < 0) { + r = bbtreedel(&(*tree)->l, item, cmp); + } else if(c > 0) { + r = bbtreedel(&(*tree)->r, item, cmp); + } else { + r = 1; + o = *tree; + if(((*tree)->r != NULL) && ((*tree)->l != NULL)) { + sp = &(*tree)->r; + s = *sp; + while(s->l != NULL) { + sp = &(s->l); + s = *sp; + } + *sp = NULL; + s->l = (*tree)->l; + s->r = (*tree)->r; + *tree = s; + } else if((*tree)->l != NULL) { + *tree = (*tree)->l; + } else if((*tree)->r != NULL) { + *tree = (*tree)->r; + } else { + *tree = NULL; + } + free(o); + } + if(*tree != NULL) { + btsetheight(*tree); + if(btheight((*tree)->l) > btheight((*tree)->r) + 1) + bbtrr(tree); + if(btheight((*tree)->r) > btheight((*tree)->l) + 1) + bbtrl(tree); + } + return(r); +} + +int bbtreeput(struct btree **tree, void *item, int (*cmp)(void *, void *)) +{ + int c, r; + + if(*tree == NULL) { + *tree = smalloc(sizeof(**tree)); + (*tree)->l = (*tree)->r = NULL; + (*tree)->d = item; + (*tree)->h = 1; + return(1); + } + if((c = cmp(item, (*tree)->d)) < 0) + r = bbtreeput(&(*tree)->l, item, cmp); + else if(c > 0) + r = bbtreeput(&(*tree)->r, item, cmp); + else + return(0); + btsetheight(*tree); + if(btheight((*tree)->l) > btheight((*tree)->r) + 1) + bbtrr(tree); + if(btheight((*tree)->r) > btheight((*tree)->l) + 1) + bbtrl(tree); + return(r); +} + +void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *)) +{ + int c; + + while(1) { + if(tree == NULL) + return(NULL); + c = cmp(key, tree->d); + if(c < 0) + tree = tree->l; + else if(c > 0) + tree = tree->r; + else + return(tree->d); + } +} + diff --git a/include/utils.h b/include/utils.h index fdcd0c3..cff0025 100644 --- a/include/utils.h +++ b/include/utils.h @@ -37,6 +37,12 @@ struct strpair { char *val; }; +struct btree { + struct btree *l, *r; + int h; + void *d; +}; + /* "Safe" functions */ #ifdef DAEMON #define LOGOOM(size) flog(LOG_CRIT, "%s (%s:%i): out of memory (alloc %zi)", __FUNCTION__, __FILE__, __LINE__, (size)) @@ -106,6 +112,9 @@ char *spfind(struct strpair *list, char *key); struct wcspair *newwcspair(wchar_t *key, wchar_t *val, struct wcspair **list); void freewcspair(struct wcspair *pair, struct wcspair **list); wchar_t *wpfind(struct wcspair *list, wchar_t *key); +int bbtreedel(struct btree **tree, void *item, int (*cmp)(void *, void *)); +int bbtreeput(struct btree **tree, void *item, int (*cmp)(void *, void *)); +void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *)); #define sizebuf(b, bs, rs, es, a) _sizebuf((void **)(void *)(b), (bs), (rs), (es), (a)) #define sizebuf2(b, rs, a) _sizebuf((void **)(void *)(&(b)), &(b ## size), (rs), sizeof(*(b)), (a))