11f9fb570SDavid du Colombier #include <u.h>
21f9fb570SDavid du Colombier #include <libc.h>
31f9fb570SDavid du Colombier #include <bio.h>
41f9fb570SDavid du Colombier #include <avl.h>
51f9fb570SDavid du Colombier
61f9fb570SDavid du Colombier /*
71f9fb570SDavid du Colombier * In-memory database stored as self-balancing AVL tree.
81f9fb570SDavid du Colombier * See Lewis & Denenberg, Data Structures and Their Algorithms.
91f9fb570SDavid du Colombier */
101f9fb570SDavid du Colombier
111f9fb570SDavid du Colombier static void
singleleft(Avl ** tp,Avl * p)121f9fb570SDavid du Colombier singleleft(Avl **tp, Avl *p)
131f9fb570SDavid du Colombier {
141f9fb570SDavid du Colombier int l, r2;
151f9fb570SDavid du Colombier Avl *a, *c;
161f9fb570SDavid du Colombier
171f9fb570SDavid du Colombier a = *tp;
181f9fb570SDavid du Colombier c = a->n[1];
191f9fb570SDavid du Colombier
201f9fb570SDavid du Colombier r2 = c->bal;
211f9fb570SDavid du Colombier l = (r2 > 0? r2: 0)+1 - a->bal;
221f9fb570SDavid du Colombier
231f9fb570SDavid du Colombier if((a->n[1] = c->n[0]) != nil)
241f9fb570SDavid du Colombier a->n[1]->p = a;
251f9fb570SDavid du Colombier
261f9fb570SDavid du Colombier if((c->n[0] = a) != nil)
271f9fb570SDavid du Colombier c->n[0]->p = c;
281f9fb570SDavid du Colombier
291f9fb570SDavid du Colombier if((*tp = c) != nil)
301f9fb570SDavid du Colombier (*tp)->p = p;
311f9fb570SDavid du Colombier
321f9fb570SDavid du Colombier a->bal = -l;
331f9fb570SDavid du Colombier c->bal = r2 - ((l > 0? l: 0)+1);
341f9fb570SDavid du Colombier
351f9fb570SDavid du Colombier }
361f9fb570SDavid du Colombier
371f9fb570SDavid du Colombier static void
singleright(Avl ** tp,Avl * p)381f9fb570SDavid du Colombier singleright(Avl **tp, Avl *p)
391f9fb570SDavid du Colombier {
401f9fb570SDavid du Colombier int l2, r;
411f9fb570SDavid du Colombier Avl *a, *c;
421f9fb570SDavid du Colombier
431f9fb570SDavid du Colombier a = *tp;
441f9fb570SDavid du Colombier c = a->n[0];
451f9fb570SDavid du Colombier l2 = - c->bal;
461f9fb570SDavid du Colombier r = a->bal + ((l2 > 0? l2: 0)+1);
471f9fb570SDavid du Colombier
481f9fb570SDavid du Colombier if((a->n[0] = c->n[1]) != nil)
491f9fb570SDavid du Colombier a->n[0]->p = a;
501f9fb570SDavid du Colombier
511f9fb570SDavid du Colombier if((c->n[1] = a) != nil)
521f9fb570SDavid du Colombier c->n[1]->p = c;
531f9fb570SDavid du Colombier
541f9fb570SDavid du Colombier if((*tp = c) != nil)
551f9fb570SDavid du Colombier (*tp)->p = p;
561f9fb570SDavid du Colombier
571f9fb570SDavid du Colombier a->bal = r;
581f9fb570SDavid du Colombier c->bal = ((r > 0? r: 0)+1) - l2;
591f9fb570SDavid du Colombier }
601f9fb570SDavid du Colombier
611f9fb570SDavid du Colombier static void
doublerightleft(Avl ** tp,Avl * p)621f9fb570SDavid du Colombier doublerightleft(Avl **tp, Avl *p)
631f9fb570SDavid du Colombier {
641f9fb570SDavid du Colombier singleright(&(*tp)->n[1], *tp);
651f9fb570SDavid du Colombier singleleft(tp, p);
661f9fb570SDavid du Colombier }
671f9fb570SDavid du Colombier
681f9fb570SDavid du Colombier static void
doubleleftright(Avl ** tp,Avl * p)691f9fb570SDavid du Colombier doubleleftright(Avl **tp, Avl *p)
701f9fb570SDavid du Colombier {
711f9fb570SDavid du Colombier singleleft(&(*tp)->n[0], *tp);
721f9fb570SDavid du Colombier singleright(tp, p);
731f9fb570SDavid du Colombier }
741f9fb570SDavid du Colombier
751f9fb570SDavid du Colombier static void
balance(Avl ** tp,Avl * p)761f9fb570SDavid du Colombier balance(Avl **tp, Avl *p)
771f9fb570SDavid du Colombier {
781f9fb570SDavid du Colombier switch((*tp)->bal){
791f9fb570SDavid du Colombier case -2:
801f9fb570SDavid du Colombier if((*tp)->n[0]->bal <= 0)
811f9fb570SDavid du Colombier singleright(tp, p);
821f9fb570SDavid du Colombier else if((*tp)->n[0]->bal == 1)
831f9fb570SDavid du Colombier doubleleftright(tp, p);
841f9fb570SDavid du Colombier else
851f9fb570SDavid du Colombier assert(0);
861f9fb570SDavid du Colombier break;
871f9fb570SDavid du Colombier
881f9fb570SDavid du Colombier case 2:
891f9fb570SDavid du Colombier if((*tp)->n[1]->bal >= 0)
901f9fb570SDavid du Colombier singleleft(tp, p);
911f9fb570SDavid du Colombier else if((*tp)->n[1]->bal == -1)
921f9fb570SDavid du Colombier doublerightleft(tp, p);
931f9fb570SDavid du Colombier else
941f9fb570SDavid du Colombier assert(0);
951f9fb570SDavid du Colombier break;
961f9fb570SDavid du Colombier }
971f9fb570SDavid du Colombier }
981f9fb570SDavid du Colombier
991f9fb570SDavid du Colombier static int
canoncmp(int cmp)100*2ecc4774SDavid du Colombier canoncmp(int cmp)
101*2ecc4774SDavid du Colombier {
102*2ecc4774SDavid du Colombier if(cmp < 0)
103*2ecc4774SDavid du Colombier return -1;
104*2ecc4774SDavid du Colombier else if(cmp > 0)
105*2ecc4774SDavid du Colombier return 1;
106*2ecc4774SDavid du Colombier return 0;
107*2ecc4774SDavid du Colombier }
108*2ecc4774SDavid du Colombier
109*2ecc4774SDavid du Colombier static int
_insertavl(Avl ** tp,Avl * p,Avl * r,int (* cmp)(Avl *,Avl *),Avl ** rfree)1101f9fb570SDavid du Colombier _insertavl(Avl **tp, Avl *p, Avl *r, int (*cmp)(Avl*,Avl*), Avl **rfree)
1111f9fb570SDavid du Colombier {
1121f9fb570SDavid du Colombier int i, ob;
1131f9fb570SDavid du Colombier
1141f9fb570SDavid du Colombier if(*tp == nil){
1151f9fb570SDavid du Colombier r->bal = 0;
1161f9fb570SDavid du Colombier r->n[0] = nil;
1171f9fb570SDavid du Colombier r->n[1] = nil;
1181f9fb570SDavid du Colombier r->p = p;
1191f9fb570SDavid du Colombier *tp = r;
1201f9fb570SDavid du Colombier return 1;
1211f9fb570SDavid du Colombier }
1221f9fb570SDavid du Colombier ob = (*tp)->bal;
123*2ecc4774SDavid du Colombier if((i = canoncmp(cmp(r, *tp))) != 0){
1241f9fb570SDavid du Colombier (*tp)->bal += i * _insertavl(&(*tp)->n[(i+1)/2], *tp, r, cmp,
1251f9fb570SDavid du Colombier rfree);
1261f9fb570SDavid du Colombier balance(tp, p);
1271f9fb570SDavid du Colombier return ob == 0 && (*tp)->bal != 0;
1281f9fb570SDavid du Colombier }
1291f9fb570SDavid du Colombier
1301f9fb570SDavid du Colombier /* install new entry */
1311f9fb570SDavid du Colombier *rfree = *tp; /* save old node for freeing */
1321f9fb570SDavid du Colombier *tp = r; /* insert new node */
1331f9fb570SDavid du Colombier **tp = **rfree; /* copy old node's Avl contents */
1341f9fb570SDavid du Colombier if(r->n[0]) /* fix node's children's parent pointers */
1351f9fb570SDavid du Colombier r->n[0]->p = r;
1361f9fb570SDavid du Colombier if(r->n[1])
1371f9fb570SDavid du Colombier r->n[1]->p = r;
1381f9fb570SDavid du Colombier
1391f9fb570SDavid du Colombier return 0;
1401f9fb570SDavid du Colombier }
1411f9fb570SDavid du Colombier
1421f9fb570SDavid du Colombier static int
successor(Avl ** tp,Avl * p,Avl ** r)1431f9fb570SDavid du Colombier successor(Avl **tp, Avl *p, Avl **r)
1441f9fb570SDavid du Colombier {
1451f9fb570SDavid du Colombier int ob;
1461f9fb570SDavid du Colombier
1471f9fb570SDavid du Colombier if((*tp)->n[0] == nil){
1481f9fb570SDavid du Colombier *r = *tp;
1491f9fb570SDavid du Colombier *tp = (*r)->n[1];
1501f9fb570SDavid du Colombier if(*tp)
1511f9fb570SDavid du Colombier (*tp)->p = p;
1521f9fb570SDavid du Colombier return -1;
1531f9fb570SDavid du Colombier }
1541f9fb570SDavid du Colombier ob = (*tp)->bal;
1551f9fb570SDavid du Colombier (*tp)->bal -= successor(&(*tp)->n[0], *tp, r);
1561f9fb570SDavid du Colombier balance(tp, p);
1571f9fb570SDavid du Colombier return -(ob != 0 && (*tp)->bal == 0);
1581f9fb570SDavid du Colombier }
1591f9fb570SDavid du Colombier
1601f9fb570SDavid du Colombier static int
_deleteavl(Avl ** tp,Avl * p,Avl * rx,int (* cmp)(Avl *,Avl *),Avl ** del,void (* predel)(Avl *,void *),void * arg)1611f9fb570SDavid du Colombier _deleteavl(Avl **tp, Avl *p, Avl *rx, int(*cmp)(Avl*,Avl*), Avl **del,
1621f9fb570SDavid du Colombier void (*predel)(Avl*, void*), void *arg)
1631f9fb570SDavid du Colombier {
1641f9fb570SDavid du Colombier int i, ob;
1651f9fb570SDavid du Colombier Avl *r, *or;
1661f9fb570SDavid du Colombier
1671f9fb570SDavid du Colombier if(*tp == nil)
1681f9fb570SDavid du Colombier return 0;
1691f9fb570SDavid du Colombier
1701f9fb570SDavid du Colombier ob = (*tp)->bal;
171*2ecc4774SDavid du Colombier if((i=canoncmp(cmp(rx, *tp))) != 0){
1721f9fb570SDavid du Colombier (*tp)->bal += i * _deleteavl(&(*tp)->n[(i+1)/2], *tp, rx, cmp,
1731f9fb570SDavid du Colombier del, predel, arg);
1741f9fb570SDavid du Colombier balance(tp, p);
1751f9fb570SDavid du Colombier return -(ob != 0 && (*tp)->bal == 0);
1761f9fb570SDavid du Colombier }
1771f9fb570SDavid du Colombier
1781f9fb570SDavid du Colombier if(predel)
1791f9fb570SDavid du Colombier (*predel)(*tp, arg);
1801f9fb570SDavid du Colombier
1811f9fb570SDavid du Colombier or = *tp;
1821f9fb570SDavid du Colombier if(or->n[i=0] == nil || or->n[i=1] == nil){
1831f9fb570SDavid du Colombier *tp = or->n[1-i];
1841f9fb570SDavid du Colombier if(*tp)
1851f9fb570SDavid du Colombier (*tp)->p = p;
1861f9fb570SDavid du Colombier *del = or;
1871f9fb570SDavid du Colombier return -1;
1881f9fb570SDavid du Colombier }
1891f9fb570SDavid du Colombier
1901f9fb570SDavid du Colombier /* deleting node with two kids, find successor */
1911f9fb570SDavid du Colombier or->bal += successor(&or->n[1], or, &r);
1921f9fb570SDavid du Colombier r->bal = or->bal;
1931f9fb570SDavid du Colombier r->n[0] = or->n[0];
1941f9fb570SDavid du Colombier r->n[1] = or->n[1];
1951f9fb570SDavid du Colombier *tp = r;
1961f9fb570SDavid du Colombier (*tp)->p = p;
1971f9fb570SDavid du Colombier /* node has changed; fix children's parent pointers */
1981f9fb570SDavid du Colombier if(r->n[0])
1991f9fb570SDavid du Colombier r->n[0]->p = r;
2001f9fb570SDavid du Colombier if(r->n[1])
2011f9fb570SDavid du Colombier r->n[1]->p = r;
2021f9fb570SDavid du Colombier *del = or;
2031f9fb570SDavid du Colombier balance(tp, p);
2041f9fb570SDavid du Colombier return -(ob != 0 && (*tp)->bal == 0);
2051f9fb570SDavid du Colombier }
2061f9fb570SDavid du Colombier
2071f9fb570SDavid du Colombier static void
checkparents(Avl * a,Avl * p)2081f9fb570SDavid du Colombier checkparents(Avl *a, Avl *p)
2091f9fb570SDavid du Colombier {
2101f9fb570SDavid du Colombier if(a == nil)
2111f9fb570SDavid du Colombier return;
2121f9fb570SDavid du Colombier if(a->p != p)
2131f9fb570SDavid du Colombier print("bad parent\n");
2141f9fb570SDavid du Colombier checkparents(a->n[0], a);
2151f9fb570SDavid du Colombier checkparents(a->n[1], a);
2161f9fb570SDavid du Colombier }
2171f9fb570SDavid du Colombier
2181f9fb570SDavid du Colombier struct Avltree
2191f9fb570SDavid du Colombier {
2201f9fb570SDavid du Colombier Avl *root;
2211f9fb570SDavid du Colombier int (*cmp)(Avl*, Avl*);
2221f9fb570SDavid du Colombier Avlwalk *walks;
2231f9fb570SDavid du Colombier };
2241f9fb570SDavid du Colombier struct Avlwalk
2251f9fb570SDavid du Colombier {
2261f9fb570SDavid du Colombier int started;
2271f9fb570SDavid du Colombier int moved;
2281f9fb570SDavid du Colombier Avlwalk *next;
2291f9fb570SDavid du Colombier Avltree *tree;
2301f9fb570SDavid du Colombier Avl *node;
2311f9fb570SDavid du Colombier };
2321f9fb570SDavid du Colombier
2331f9fb570SDavid du Colombier Avltree*
mkavltree(int (* cmp)(Avl *,Avl *))2341f9fb570SDavid du Colombier mkavltree(int (*cmp)(Avl*, Avl*))
2351f9fb570SDavid du Colombier {
2361f9fb570SDavid du Colombier Avltree *t;
2371f9fb570SDavid du Colombier
2381f9fb570SDavid du Colombier t = malloc(sizeof *t);
2391f9fb570SDavid du Colombier if(t == nil)
2401f9fb570SDavid du Colombier return nil;
2411f9fb570SDavid du Colombier memset(t, 0, sizeof *t);
2421f9fb570SDavid du Colombier t->cmp = cmp;
2431f9fb570SDavid du Colombier return t;
2441f9fb570SDavid du Colombier }
2451f9fb570SDavid du Colombier
2461f9fb570SDavid du Colombier void
insertavl(Avltree * t,Avl * new,Avl ** oldp)2471f9fb570SDavid du Colombier insertavl(Avltree *t, Avl *new, Avl **oldp)
2481f9fb570SDavid du Colombier {
2491f9fb570SDavid du Colombier *oldp = nil;
2501f9fb570SDavid du Colombier _insertavl(&t->root, nil, new, t->cmp, oldp);
2511f9fb570SDavid du Colombier }
2521f9fb570SDavid du Colombier
2531f9fb570SDavid du Colombier static Avl*
findpredecessor(Avl * a)2541f9fb570SDavid du Colombier findpredecessor(Avl *a)
2551f9fb570SDavid du Colombier {
2561f9fb570SDavid du Colombier if(a == nil)
2571f9fb570SDavid du Colombier return nil;
2581f9fb570SDavid du Colombier
2591f9fb570SDavid du Colombier if(a->n[0] != nil){
2601f9fb570SDavid du Colombier /* predecessor is rightmost descendant of left child */
2611f9fb570SDavid du Colombier for(a = a->n[0]; a->n[1]; a = a->n[1])
2621f9fb570SDavid du Colombier ;
2631f9fb570SDavid du Colombier return a;
2641f9fb570SDavid du Colombier }else{
2651f9fb570SDavid du Colombier /* we're at a leaf, successor is a parent we enter from the right */
2661f9fb570SDavid du Colombier while(a->p && a->p->n[0] == a)
2671f9fb570SDavid du Colombier a = a->p;
2681f9fb570SDavid du Colombier return a->p;
2691f9fb570SDavid du Colombier }
2701f9fb570SDavid du Colombier }
2711f9fb570SDavid du Colombier
2721f9fb570SDavid du Colombier static Avl*
findsuccessor(Avl * a)2731f9fb570SDavid du Colombier findsuccessor(Avl *a)
2741f9fb570SDavid du Colombier {
2751f9fb570SDavid du Colombier if(a == nil)
2761f9fb570SDavid du Colombier return nil;
2771f9fb570SDavid du Colombier
2781f9fb570SDavid du Colombier if(a->n[1] != nil){
2791f9fb570SDavid du Colombier /* successor is leftmost descendant of right child */
2801f9fb570SDavid du Colombier for(a = a->n[1]; a->n[0]; a = a->n[0])
2811f9fb570SDavid du Colombier ;
2821f9fb570SDavid du Colombier return a;
2831f9fb570SDavid du Colombier }else{
2841f9fb570SDavid du Colombier /* we're at a leaf, successor is a parent we enter from the left going up */
2851f9fb570SDavid du Colombier while(a->p && a->p->n[1] == a)
2861f9fb570SDavid du Colombier a = a->p;
2871f9fb570SDavid du Colombier return a->p;
2881f9fb570SDavid du Colombier }
2891f9fb570SDavid du Colombier }
2901f9fb570SDavid du Colombier
291c54d4d90SDavid du Colombier static Avl*
_lookupavl(Avl * t,Avl * r,int (* cmp)(Avl *,Avl *),int neighbor)292c54d4d90SDavid du Colombier _lookupavl(Avl *t, Avl *r, int (*cmp)(Avl*,Avl*), int neighbor)
293c54d4d90SDavid du Colombier {
294c54d4d90SDavid du Colombier int i;
295c54d4d90SDavid du Colombier Avl *p;
296c54d4d90SDavid du Colombier
297c54d4d90SDavid du Colombier p = nil;
298c54d4d90SDavid du Colombier if(t == nil)
299c54d4d90SDavid du Colombier return nil;
300c54d4d90SDavid du Colombier do{
301c54d4d90SDavid du Colombier assert(t->p == p);
302*2ecc4774SDavid du Colombier if((i = canoncmp(cmp(r, t))) == 0)
303c54d4d90SDavid du Colombier return t;
304c54d4d90SDavid du Colombier p = t;
305c54d4d90SDavid du Colombier t = t->n[(i+1)/2];
306c54d4d90SDavid du Colombier }while(t);
307c54d4d90SDavid du Colombier if(neighbor == 0)
308c54d4d90SDavid du Colombier return nil;
309c54d4d90SDavid du Colombier if(neighbor < 0)
310c54d4d90SDavid du Colombier return i > 0 ? p : findpredecessor(p);
311c54d4d90SDavid du Colombier return i < 0 ? p : findsuccessor(p);
312c54d4d90SDavid du Colombier }
313c54d4d90SDavid du Colombier
314c54d4d90SDavid du Colombier Avl*
searchavl(Avltree * t,Avl * key,int neighbor)315c54d4d90SDavid du Colombier searchavl(Avltree *t, Avl *key, int neighbor)
316c54d4d90SDavid du Colombier {
317c54d4d90SDavid du Colombier return _lookupavl(t->root, key, t->cmp, neighbor);
318c54d4d90SDavid du Colombier }
319c54d4d90SDavid du Colombier
320c54d4d90SDavid du Colombier Avl*
lookupavl(Avltree * t,Avl * key)321c54d4d90SDavid du Colombier lookupavl(Avltree *t, Avl *key)
322c54d4d90SDavid du Colombier {
323c54d4d90SDavid du Colombier return _lookupavl(t->root, key, t->cmp, 0);
324c54d4d90SDavid du Colombier }
325c54d4d90SDavid du Colombier
3261f9fb570SDavid du Colombier static void
walkdel(Avl * a,void * v)3271f9fb570SDavid du Colombier walkdel(Avl *a, void *v)
3281f9fb570SDavid du Colombier {
3291f9fb570SDavid du Colombier Avl *p;
3301f9fb570SDavid du Colombier Avlwalk *w;
3311f9fb570SDavid du Colombier Avltree *t;
3321f9fb570SDavid du Colombier
3331f9fb570SDavid du Colombier if(a == nil)
3341f9fb570SDavid du Colombier return;
3351f9fb570SDavid du Colombier
3361f9fb570SDavid du Colombier p = findpredecessor(a);
3371f9fb570SDavid du Colombier t = v;
3381f9fb570SDavid du Colombier for(w = t->walks; w; w = w->next){
3391f9fb570SDavid du Colombier if(w->node == a){
3401f9fb570SDavid du Colombier /* back pointer to predecessor; not perfect but adequate */
3411f9fb570SDavid du Colombier w->moved = 1;
3421f9fb570SDavid du Colombier w->node = p;
3431f9fb570SDavid du Colombier if(p == nil)
3441f9fb570SDavid du Colombier w->started = 0;
3451f9fb570SDavid du Colombier }
3461f9fb570SDavid du Colombier }
3471f9fb570SDavid du Colombier }
3481f9fb570SDavid du Colombier
3491f9fb570SDavid du Colombier void
deleteavl(Avltree * t,Avl * key,Avl ** oldp)3501f9fb570SDavid du Colombier deleteavl(Avltree *t, Avl *key, Avl **oldp)
3511f9fb570SDavid du Colombier {
3521f9fb570SDavid du Colombier *oldp = nil;
3531f9fb570SDavid du Colombier _deleteavl(&t->root, nil, key, t->cmp, oldp, walkdel, t);
3541f9fb570SDavid du Colombier }
3551f9fb570SDavid du Colombier
3561f9fb570SDavid du Colombier Avlwalk*
avlwalk(Avltree * t)3571f9fb570SDavid du Colombier avlwalk(Avltree *t)
3581f9fb570SDavid du Colombier {
3591f9fb570SDavid du Colombier Avlwalk *w;
3601f9fb570SDavid du Colombier
3611f9fb570SDavid du Colombier w = malloc(sizeof *w);
3621f9fb570SDavid du Colombier if(w == nil)
3631f9fb570SDavid du Colombier return nil;
3641f9fb570SDavid du Colombier memset(w, 0, sizeof *w);
3651f9fb570SDavid du Colombier w->tree = t;
3661f9fb570SDavid du Colombier w->next = t->walks;
3671f9fb570SDavid du Colombier t->walks = w;
3681f9fb570SDavid du Colombier return w;
3691f9fb570SDavid du Colombier }
3701f9fb570SDavid du Colombier
3711f9fb570SDavid du Colombier Avl*
avlnext(Avlwalk * w)3721f9fb570SDavid du Colombier avlnext(Avlwalk *w)
3731f9fb570SDavid du Colombier {
3741f9fb570SDavid du Colombier Avl *a;
3751f9fb570SDavid du Colombier
3761f9fb570SDavid du Colombier if(w->started==0){
3771f9fb570SDavid du Colombier for(a = w->tree->root; a && a->n[0]; a = a->n[0])
3781f9fb570SDavid du Colombier ;
3791f9fb570SDavid du Colombier w->node = a;
3801f9fb570SDavid du Colombier w->started = 1;
3811f9fb570SDavid du Colombier }else{
3821f9fb570SDavid du Colombier a = findsuccessor(w->node);
3831f9fb570SDavid du Colombier if(a == w->node)
3841f9fb570SDavid du Colombier abort();
3851f9fb570SDavid du Colombier w->node = a;
3861f9fb570SDavid du Colombier }
3871f9fb570SDavid du Colombier return w->node;
3881f9fb570SDavid du Colombier }
3891f9fb570SDavid du Colombier
3901f9fb570SDavid du Colombier Avl*
avlprev(Avlwalk * w)3911f9fb570SDavid du Colombier avlprev(Avlwalk *w)
3921f9fb570SDavid du Colombier {
3931f9fb570SDavid du Colombier Avl *a;
3941f9fb570SDavid du Colombier
3951f9fb570SDavid du Colombier if(w->started == 0){
3961f9fb570SDavid du Colombier for(a = w->tree->root; a && a->n[1]; a = a->n[1])
3971f9fb570SDavid du Colombier ;
3981f9fb570SDavid du Colombier w->node = a;
3991f9fb570SDavid du Colombier w->started = 1;
4001f9fb570SDavid du Colombier }else if(w->moved){
4011f9fb570SDavid du Colombier w->moved = 0;
4021f9fb570SDavid du Colombier return w->node;
4031f9fb570SDavid du Colombier }else{
4041f9fb570SDavid du Colombier a = findpredecessor(w->node);
4051f9fb570SDavid du Colombier if(a == w->node)
4061f9fb570SDavid du Colombier abort();
4071f9fb570SDavid du Colombier w->node = a;
4081f9fb570SDavid du Colombier }
4091f9fb570SDavid du Colombier return w->node;
4101f9fb570SDavid du Colombier }
4111f9fb570SDavid du Colombier
4121f9fb570SDavid du Colombier void
endwalk(Avlwalk * w)4131f9fb570SDavid du Colombier endwalk(Avlwalk *w)
4141f9fb570SDavid du Colombier {
4151f9fb570SDavid du Colombier Avltree *t;
4161f9fb570SDavid du Colombier Avlwalk **l;
4171f9fb570SDavid du Colombier
4181f9fb570SDavid du Colombier t = w->tree;
4191f9fb570SDavid du Colombier for(l = &t->walks; *l; l = &(*l)->next){
4201f9fb570SDavid du Colombier if(*l == w){
4211f9fb570SDavid du Colombier *l = w->next;
4221f9fb570SDavid du Colombier break;
4231f9fb570SDavid du Colombier }
4241f9fb570SDavid du Colombier }
4251f9fb570SDavid du Colombier free(w);
4261f9fb570SDavid du Colombier }
4271f9fb570SDavid du Colombier
4281f9fb570SDavid du Colombier static void
walkavl(Avl * t,void (* f)(Avl *,void *),void * v)4291f9fb570SDavid du Colombier walkavl(Avl *t, void (*f)(Avl*, void*), void *v)
4301f9fb570SDavid du Colombier {
4311f9fb570SDavid du Colombier if(t == nil)
4321f9fb570SDavid du Colombier return;
4331f9fb570SDavid du Colombier walkavl(t->n[0], f, v);
4341f9fb570SDavid du Colombier f(t, v);
4351f9fb570SDavid du Colombier walkavl(t->n[1], f, v);
4361f9fb570SDavid du Colombier }
437