|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <bio.h> | 
|  | #include <avl.h> | 
|  |  | 
|  | /* | 
|  | * In-memory database stored as self-balancing AVL tree. | 
|  | * See Lewis & Denenberg, Data Structures and Their Algorithms. | 
|  | */ | 
|  |  | 
|  | static void | 
|  | singleleft(Avl **tp, Avl *p) | 
|  | { | 
|  | int l, r2; | 
|  | Avl *a, *c; | 
|  |  | 
|  | a = *tp; | 
|  | c = a->n[1]; | 
|  |  | 
|  | r2 = c->bal; | 
|  | l = (r2 > 0? r2: 0)+1 - a->bal; | 
|  |  | 
|  | if((a->n[1] = c->n[0]) != nil) | 
|  | a->n[1]->p = a; | 
|  |  | 
|  | if((c->n[0] = a) != nil) | 
|  | c->n[0]->p = c; | 
|  |  | 
|  | if((*tp = c) != nil) | 
|  | (*tp)->p = p; | 
|  |  | 
|  | a->bal = -l; | 
|  | c->bal = r2 - ((l > 0? l: 0)+1); | 
|  |  | 
|  | } | 
|  |  | 
|  | static void | 
|  | singleright(Avl **tp, Avl *p) | 
|  | { | 
|  | int l2, r; | 
|  | Avl *a, *c; | 
|  |  | 
|  | a = *tp; | 
|  | c = a->n[0]; | 
|  | l2 = - c->bal; | 
|  | r = a->bal + ((l2 > 0? l2: 0)+1); | 
|  |  | 
|  | if((a->n[0] = c->n[1]) != nil) | 
|  | a->n[0]->p = a; | 
|  |  | 
|  | if((c->n[1] = a) != nil) | 
|  | c->n[1]->p = c; | 
|  |  | 
|  | if((*tp = c) != nil) | 
|  | (*tp)->p = p; | 
|  |  | 
|  | a->bal = r; | 
|  | c->bal = ((r > 0? r: 0)+1) - l2; | 
|  | } | 
|  |  | 
|  | static void | 
|  | doublerightleft(Avl **tp, Avl *p) | 
|  | { | 
|  | singleright(&(*tp)->n[1], *tp); | 
|  | singleleft(tp, p); | 
|  | } | 
|  |  | 
|  | static void | 
|  | doubleleftright(Avl **tp, Avl *p) | 
|  | { | 
|  | singleleft(&(*tp)->n[0], *tp); | 
|  | singleright(tp, p); | 
|  | } | 
|  |  | 
|  | static void | 
|  | balance(Avl **tp, Avl *p) | 
|  | { | 
|  | switch((*tp)->bal){ | 
|  | case -2: | 
|  | if((*tp)->n[0]->bal <= 0) | 
|  | singleright(tp, p); | 
|  | else if((*tp)->n[0]->bal == 1) | 
|  | doubleleftright(tp, p); | 
|  | else | 
|  | assert(0); | 
|  | break; | 
|  |  | 
|  | case 2: | 
|  | if((*tp)->n[1]->bal >= 0) | 
|  | singleleft(tp, p); | 
|  | else if((*tp)->n[1]->bal == -1) | 
|  | doublerightleft(tp, p); | 
|  | else | 
|  | assert(0); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | static int | 
|  | _insertavl(Avl **tp, Avl *p, Avl *r, int (*cmp)(Avl*,Avl*), Avl **rfree) | 
|  | { | 
|  | int i, ob; | 
|  |  | 
|  | if(*tp == nil){ | 
|  | r->bal = 0; | 
|  | r->n[0] = nil; | 
|  | r->n[1] = nil; | 
|  | r->p = p; | 
|  | *tp = r; | 
|  | return 1; | 
|  | } | 
|  | ob = (*tp)->bal; | 
|  | if((i = cmp(r, *tp)) != 0){ | 
|  | (*tp)->bal += i * _insertavl(&(*tp)->n[(i+1)/2], *tp, r, cmp, | 
|  | rfree); | 
|  | balance(tp, p); | 
|  | return ob == 0 && (*tp)->bal != 0; | 
|  | } | 
|  |  | 
|  | /* install new entry */ | 
|  | *rfree = *tp;		/* save old node for freeing */ | 
|  | *tp = r;		/* insert new node */ | 
|  | **tp = **rfree;		/* copy old node's Avl contents */ | 
|  | if(r->n[0])		/* fix node's children's parent pointers */ | 
|  | r->n[0]->p = r; | 
|  | if(r->n[1]) | 
|  | r->n[1]->p = r; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static Avl* | 
|  | _lookupavl(Avl *t, Avl *r, int (*cmp)(Avl*,Avl*)) | 
|  | { | 
|  | int i; | 
|  | Avl *p; | 
|  |  | 
|  | p = nil; | 
|  | while(t != nil){ | 
|  | assert(t->p == p); | 
|  | if((i = cmp(r, t)) == 0) | 
|  | return t; | 
|  | p = t; | 
|  | t = t->n[(i+1)/2]; | 
|  | } | 
|  | return nil; | 
|  | } | 
|  |  | 
|  | static int | 
|  | successor(Avl **tp, Avl *p, Avl **r) | 
|  | { | 
|  | int ob; | 
|  |  | 
|  | if((*tp)->n[0] == nil){ | 
|  | *r = *tp; | 
|  | *tp = (*r)->n[1]; | 
|  | if(*tp) | 
|  | (*tp)->p = p; | 
|  | return -1; | 
|  | } | 
|  | ob = (*tp)->bal; | 
|  | (*tp)->bal -= successor(&(*tp)->n[0], *tp, r); | 
|  | balance(tp, p); | 
|  | return -(ob != 0 && (*tp)->bal == 0); | 
|  | } | 
|  |  | 
|  | static int | 
|  | _deleteavl(Avl **tp, Avl *p, Avl *rx, int(*cmp)(Avl*,Avl*), Avl **del, | 
|  | void (*predel)(Avl*, void*), void *arg) | 
|  | { | 
|  | int i, ob; | 
|  | Avl *r, *or; | 
|  |  | 
|  | if(*tp == nil) | 
|  | return 0; | 
|  |  | 
|  | ob = (*tp)->bal; | 
|  | if((i=cmp(rx, *tp)) != 0){ | 
|  | (*tp)->bal += i * _deleteavl(&(*tp)->n[(i+1)/2], *tp, rx, cmp, | 
|  | del, predel, arg); | 
|  | balance(tp, p); | 
|  | return -(ob != 0 && (*tp)->bal == 0); | 
|  | } | 
|  |  | 
|  | if(predel) | 
|  | (*predel)(*tp, arg); | 
|  |  | 
|  | or = *tp; | 
|  | if(or->n[i=0] == nil || or->n[i=1] == nil){ | 
|  | *tp = or->n[1-i]; | 
|  | if(*tp) | 
|  | (*tp)->p = p; | 
|  | *del = or; | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* deleting node with two kids, find successor */ | 
|  | or->bal += successor(&or->n[1], or, &r); | 
|  | r->bal = or->bal; | 
|  | r->n[0] = or->n[0]; | 
|  | r->n[1] = or->n[1]; | 
|  | *tp = r; | 
|  | (*tp)->p = p; | 
|  | /* node has changed; fix children's parent pointers */ | 
|  | if(r->n[0]) | 
|  | r->n[0]->p = r; | 
|  | if(r->n[1]) | 
|  | r->n[1]->p = r; | 
|  | *del = or; | 
|  | balance(tp, p); | 
|  | return -(ob != 0 && (*tp)->bal == 0); | 
|  | } | 
|  |  | 
|  | static void | 
|  | checkparents(Avl *a, Avl *p) | 
|  | { | 
|  | if(a == nil) | 
|  | return; | 
|  | if(a->p != p) | 
|  | print("bad parent\n"); | 
|  | checkparents(a->n[0], a); | 
|  | checkparents(a->n[1], a); | 
|  | } | 
|  |  | 
|  | struct Avltree | 
|  | { | 
|  | Avl	*root; | 
|  | int	(*cmp)(Avl*, Avl*); | 
|  | Avlwalk	*walks; | 
|  | }; | 
|  | struct Avlwalk | 
|  | { | 
|  | int	started; | 
|  | int	moved; | 
|  | Avlwalk	*next; | 
|  | Avltree	*tree; | 
|  | Avl	*node; | 
|  | }; | 
|  |  | 
|  | Avltree* | 
|  | mkavltree(int (*cmp)(Avl*, Avl*)) | 
|  | { | 
|  | Avltree *t; | 
|  |  | 
|  | t = malloc(sizeof *t); | 
|  | if(t == nil) | 
|  | return nil; | 
|  | memset(t, 0, sizeof *t); | 
|  | t->cmp = cmp; | 
|  | return t; | 
|  | } | 
|  |  | 
|  | void | 
|  | insertavl(Avltree *t, Avl *new, Avl **oldp) | 
|  | { | 
|  | *oldp = nil; | 
|  | _insertavl(&t->root, nil, new, t->cmp, oldp); | 
|  | } | 
|  |  | 
|  | Avl* | 
|  | lookupavl(Avltree *t, Avl *key) | 
|  | { | 
|  | return _lookupavl(t->root, key, t->cmp); | 
|  | } | 
|  |  | 
|  | static Avl* | 
|  | findpredecessor(Avl *a) | 
|  | { | 
|  | if(a == nil) | 
|  | return nil; | 
|  |  | 
|  | if(a->n[0] != nil){ | 
|  | /* predecessor is rightmost descendant of left child */ | 
|  | for(a = a->n[0]; a->n[1]; a = a->n[1]) | 
|  | ; | 
|  | return a; | 
|  | }else{ | 
|  | /* we're at a leaf, successor is a parent we enter from the right */ | 
|  | while(a->p && a->p->n[0] == a) | 
|  | a = a->p; | 
|  | return a->p; | 
|  | } | 
|  | } | 
|  |  | 
|  | static Avl* | 
|  | findsuccessor(Avl *a) | 
|  | { | 
|  | if(a == nil) | 
|  | return nil; | 
|  |  | 
|  | if(a->n[1] != nil){ | 
|  | /* successor is leftmost descendant of right child */ | 
|  | for(a = a->n[1]; a->n[0]; a = a->n[0]) | 
|  | ; | 
|  | return a; | 
|  | }else{ | 
|  | /* we're at a leaf, successor is a parent we enter from the left going up */ | 
|  | while(a->p && a->p->n[1] == a) | 
|  | a = a->p; | 
|  | return a->p; | 
|  | } | 
|  | } | 
|  |  | 
|  | static void | 
|  | walkdel(Avl *a, void *v) | 
|  | { | 
|  | Avl *p; | 
|  | Avlwalk *w; | 
|  | Avltree *t; | 
|  |  | 
|  | if(a == nil) | 
|  | return; | 
|  |  | 
|  | p = findpredecessor(a); | 
|  | t = v; | 
|  | for(w = t->walks; w; w = w->next){ | 
|  | if(w->node == a){ | 
|  | /* back pointer to predecessor; not perfect but adequate */ | 
|  | w->moved = 1; | 
|  | w->node = p; | 
|  | if(p == nil) | 
|  | w->started = 0; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void | 
|  | deleteavl(Avltree *t, Avl *key, Avl **oldp) | 
|  | { | 
|  | *oldp = nil; | 
|  | _deleteavl(&t->root, nil, key, t->cmp, oldp, walkdel, t); | 
|  | } | 
|  |  | 
|  | Avlwalk* | 
|  | avlwalk(Avltree *t) | 
|  | { | 
|  | Avlwalk *w; | 
|  |  | 
|  | w = malloc(sizeof *w); | 
|  | if(w == nil) | 
|  | return nil; | 
|  | memset(w, 0, sizeof *w); | 
|  | w->tree = t; | 
|  | w->next = t->walks; | 
|  | t->walks = w; | 
|  | return w; | 
|  | } | 
|  |  | 
|  | Avl* | 
|  | avlnext(Avlwalk *w) | 
|  | { | 
|  | Avl *a; | 
|  |  | 
|  | if(w->started==0){ | 
|  | for(a = w->tree->root; a && a->n[0]; a = a->n[0]) | 
|  | ; | 
|  | w->node = a; | 
|  | w->started = 1; | 
|  | }else{ | 
|  | a = findsuccessor(w->node); | 
|  | if(a == w->node) | 
|  | abort(); | 
|  | w->node = a; | 
|  | } | 
|  | return w->node; | 
|  | } | 
|  |  | 
|  | Avl* | 
|  | avlprev(Avlwalk *w) | 
|  | { | 
|  | Avl *a; | 
|  |  | 
|  | if(w->started == 0){ | 
|  | for(a = w->tree->root; a && a->n[1]; a = a->n[1]) | 
|  | ; | 
|  | w->node = a; | 
|  | w->started = 1; | 
|  | }else if(w->moved){ | 
|  | w->moved = 0; | 
|  | return w->node; | 
|  | }else{ | 
|  | a = findpredecessor(w->node); | 
|  | if(a == w->node) | 
|  | abort(); | 
|  | w->node = a; | 
|  | } | 
|  | return w->node; | 
|  | } | 
|  |  | 
|  | void | 
|  | endwalk(Avlwalk *w) | 
|  | { | 
|  | Avltree *t; | 
|  | Avlwalk **l; | 
|  |  | 
|  | t = w->tree; | 
|  | for(l = &t->walks; *l; l = &(*l)->next){ | 
|  | if(*l == w){ | 
|  | *l = w->next; | 
|  | break; | 
|  | } | 
|  | } | 
|  | free(w); | 
|  | } | 
|  |  | 
|  | static void | 
|  | walkavl(Avl *t, void (*f)(Avl*, void*), void *v) | 
|  | { | 
|  | if(t == nil) | 
|  | return; | 
|  | walkavl(t->n[0], f, v); | 
|  | f(t, v); | 
|  | walkavl(t->n[1], f, v); | 
|  | } |