19a747e4fSDavid du Colombier #include "all.h"
29a747e4fSDavid du Colombier
39a747e4fSDavid du Colombier /*
49a747e4fSDavid du Colombier * In-memory database stored as self-balancing AVL tree.
59a747e4fSDavid du Colombier * See Lewis & Denenberg, Data Structures and Their Algorithms.
69a747e4fSDavid du Colombier */
79a747e4fSDavid du Colombier static void
singleleft(Avl ** tp,Avl * p)89a747e4fSDavid du Colombier singleleft(Avl **tp, Avl *p)
99a747e4fSDavid du Colombier {
109a747e4fSDavid du Colombier Avl *a, *c;
119a747e4fSDavid du Colombier int l, r2;
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier a = *tp;
149a747e4fSDavid du Colombier c = a->n[1];
159a747e4fSDavid du Colombier
169a747e4fSDavid du Colombier r2 = c->bal;
179a747e4fSDavid du Colombier l = (r2 > 0 ? r2 : 0)+1 - a->bal;
189a747e4fSDavid du Colombier
199a747e4fSDavid du Colombier if((a->n[1] = c->n[0]) != nil)
209a747e4fSDavid du Colombier a->n[1]->p = a;
219a747e4fSDavid du Colombier
229a747e4fSDavid du Colombier if((c->n[0] = a) != nil)
239a747e4fSDavid du Colombier c->n[0]->p = c;
249a747e4fSDavid du Colombier
259a747e4fSDavid du Colombier if((*tp = c) != nil)
269a747e4fSDavid du Colombier (*tp)->p = p;
279a747e4fSDavid du Colombier
289a747e4fSDavid du Colombier a->bal = -l;
299a747e4fSDavid du Colombier c->bal = r2 - ((l > 0 ? l : 0)+1);
309a747e4fSDavid du Colombier
319a747e4fSDavid du Colombier }
329a747e4fSDavid du Colombier
339a747e4fSDavid du Colombier static void
singleright(Avl ** tp,Avl * p)349a747e4fSDavid du Colombier singleright(Avl **tp, Avl *p)
359a747e4fSDavid du Colombier {
369a747e4fSDavid du Colombier Avl *a, *c;
379a747e4fSDavid du Colombier int l2, r;
389a747e4fSDavid du Colombier
399a747e4fSDavid du Colombier a = *tp;
409a747e4fSDavid du Colombier c = a->n[0];
419a747e4fSDavid du Colombier l2 = - c->bal;
429a747e4fSDavid du Colombier r = a->bal + ((l2 > 0 ? l2 : 0)+1);
439a747e4fSDavid du Colombier
449a747e4fSDavid du Colombier if((a->n[0] = c->n[1]) != nil)
459a747e4fSDavid du Colombier a->n[0]->p = a;
469a747e4fSDavid du Colombier
479a747e4fSDavid du Colombier if((c->n[1] = a) != nil)
489a747e4fSDavid du Colombier c->n[1]->p = c;
499a747e4fSDavid du Colombier
509a747e4fSDavid du Colombier if((*tp = c) != nil)
519a747e4fSDavid du Colombier (*tp)->p = p;
529a747e4fSDavid du Colombier
539a747e4fSDavid du Colombier a->bal = r;
549a747e4fSDavid du Colombier c->bal = ((r > 0 ? r : 0)+1) - l2;
559a747e4fSDavid du Colombier }
569a747e4fSDavid du Colombier
579a747e4fSDavid du Colombier static void
doublerightleft(Avl ** tp,Avl * p)589a747e4fSDavid du Colombier doublerightleft(Avl **tp, Avl *p)
599a747e4fSDavid du Colombier {
609a747e4fSDavid du Colombier singleright(&(*tp)->n[1], *tp);
619a747e4fSDavid du Colombier singleleft(tp, p);
629a747e4fSDavid du Colombier }
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier static void
doubleleftright(Avl ** tp,Avl * p)659a747e4fSDavid du Colombier doubleleftright(Avl **tp, Avl *p)
669a747e4fSDavid du Colombier {
679a747e4fSDavid du Colombier singleleft(&(*tp)->n[0], *tp);
689a747e4fSDavid du Colombier singleright(tp, p);
699a747e4fSDavid du Colombier }
709a747e4fSDavid du Colombier
719a747e4fSDavid du Colombier static void
balance(Avl ** tp,Avl * p)729a747e4fSDavid du Colombier balance(Avl **tp, Avl *p)
739a747e4fSDavid du Colombier {
749a747e4fSDavid du Colombier switch((*tp)->bal){
759a747e4fSDavid du Colombier case -2:
769a747e4fSDavid du Colombier if((*tp)->n[0]->bal <= 0)
779a747e4fSDavid du Colombier singleright(tp, p);
789a747e4fSDavid du Colombier else if((*tp)->n[0]->bal == 1)
799a747e4fSDavid du Colombier doubleleftright(tp, p);
809a747e4fSDavid du Colombier else
819a747e4fSDavid du Colombier assert(0);
829a747e4fSDavid du Colombier break;
839a747e4fSDavid du Colombier
849a747e4fSDavid du Colombier case 2:
859a747e4fSDavid du Colombier if((*tp)->n[1]->bal >= 0)
869a747e4fSDavid du Colombier singleleft(tp, p);
879a747e4fSDavid du Colombier else if((*tp)->n[1]->bal == -1)
889a747e4fSDavid du Colombier doublerightleft(tp, p);
899a747e4fSDavid du Colombier else
909a747e4fSDavid du Colombier assert(0);
919a747e4fSDavid du Colombier break;
929a747e4fSDavid du Colombier }
939a747e4fSDavid du Colombier }
949a747e4fSDavid du Colombier
959a747e4fSDavid du Colombier static int
canoncmp(int cmp)96*2ecc4774SDavid du Colombier canoncmp(int cmp)
97*2ecc4774SDavid du Colombier {
98*2ecc4774SDavid du Colombier if(cmp < 0)
99*2ecc4774SDavid du Colombier return -1;
100*2ecc4774SDavid du Colombier else if(cmp > 0)
101*2ecc4774SDavid du Colombier return 1;
102*2ecc4774SDavid du Colombier return 0;
103*2ecc4774SDavid du Colombier }
104*2ecc4774SDavid du Colombier
105*2ecc4774SDavid du Colombier static int
_insertavl(Avl ** tp,Avl * p,Avl * r,int (* cmp)(Avl *,Avl *),Avl ** rfree)1069a747e4fSDavid du Colombier _insertavl(Avl **tp, Avl *p, Avl *r, int (*cmp)(Avl*,Avl*), Avl **rfree)
1079a747e4fSDavid du Colombier {
1089a747e4fSDavid du Colombier int i, ob;
1099a747e4fSDavid du Colombier
1109a747e4fSDavid du Colombier if(*tp == nil){
1119a747e4fSDavid du Colombier r->bal = 0;
1129a747e4fSDavid du Colombier r->n[0] = nil;
1139a747e4fSDavid du Colombier r->n[1] = nil;
1149a747e4fSDavid du Colombier r->p = p;
1159a747e4fSDavid du Colombier *tp = r;
1169a747e4fSDavid du Colombier return 1;
1179a747e4fSDavid du Colombier }
1189a747e4fSDavid du Colombier ob = (*tp)->bal;
119*2ecc4774SDavid du Colombier if((i=canoncmp(cmp(r, *tp))) != 0){
1209a747e4fSDavid du Colombier (*tp)->bal += i*_insertavl(&(*tp)->n[(i+1)/2], *tp, r, cmp, rfree);
1219a747e4fSDavid du Colombier balance(tp, p);
1229a747e4fSDavid du Colombier return ob==0 && (*tp)->bal != 0;
1239a747e4fSDavid du Colombier }
1249a747e4fSDavid du Colombier
1259a747e4fSDavid du Colombier /* install new entry */
1269a747e4fSDavid du Colombier *rfree = *tp; /* save old node for freeing */
1279a747e4fSDavid du Colombier *tp = r; /* insert new node */
1289a747e4fSDavid du Colombier **tp = **rfree; /* copy old node's Avl contents */
1299a747e4fSDavid du Colombier if(r->n[0]) /* fix node's children's parent pointers */
1309a747e4fSDavid du Colombier r->n[0]->p = r;
1319a747e4fSDavid du Colombier if(r->n[1])
1329a747e4fSDavid du Colombier r->n[1]->p = r;
1339a747e4fSDavid du Colombier
1349a747e4fSDavid du Colombier return 0;
1359a747e4fSDavid du Colombier }
1369a747e4fSDavid du Colombier
1379a747e4fSDavid du Colombier static Avl*
_lookupavl(Avl * t,Avl * r,int (* cmp)(Avl *,Avl *))1389a747e4fSDavid du Colombier _lookupavl(Avl *t, Avl *r, int (*cmp)(Avl*,Avl*))
1399a747e4fSDavid du Colombier {
1409a747e4fSDavid du Colombier int i;
1419a747e4fSDavid du Colombier Avl *p;
1429a747e4fSDavid du Colombier
1439a747e4fSDavid du Colombier p = nil;
1449a747e4fSDavid du Colombier while(t != nil){
1459a747e4fSDavid du Colombier assert(t->p == p);
146*2ecc4774SDavid du Colombier if((i=canoncmp(cmp(r, t)))==0)
1479a747e4fSDavid du Colombier return t;
1489a747e4fSDavid du Colombier p = t;
1499a747e4fSDavid du Colombier t = t->n[(i+1)/2];
1509a747e4fSDavid du Colombier }
1519a747e4fSDavid du Colombier return nil;
1529a747e4fSDavid du Colombier }
1539a747e4fSDavid du Colombier
1549a747e4fSDavid du Colombier static int
successor(Avl ** tp,Avl * p,Avl ** r)1559a747e4fSDavid du Colombier successor(Avl **tp, Avl *p, Avl **r)
1569a747e4fSDavid du Colombier {
1579a747e4fSDavid du Colombier int ob;
1589a747e4fSDavid du Colombier
1599a747e4fSDavid du Colombier if((*tp)->n[0] == nil){
1609a747e4fSDavid du Colombier *r = *tp;
1619a747e4fSDavid du Colombier *tp = (*r)->n[1];
1629a747e4fSDavid du Colombier if(*tp)
1639a747e4fSDavid du Colombier (*tp)->p = p;
1649a747e4fSDavid du Colombier return -1;
1659a747e4fSDavid du Colombier }
1669a747e4fSDavid du Colombier ob = (*tp)->bal;
1679a747e4fSDavid du Colombier (*tp)->bal -= successor(&(*tp)->n[0], *tp, r);
1689a747e4fSDavid du Colombier balance(tp, p);
1699a747e4fSDavid du Colombier return -(ob!=0 && (*tp)->bal==0);
1709a747e4fSDavid du Colombier }
1719a747e4fSDavid du Colombier
1729a747e4fSDavid du Colombier static int
_deleteavl(Avl ** tp,Avl * p,Avl * rx,int (* cmp)(Avl *,Avl *),Avl ** del,void (* predel)(Avl *,void *),void * arg)1739a747e4fSDavid du Colombier _deleteavl(Avl **tp, Avl *p, Avl *rx, int(*cmp)(Avl*,Avl*), Avl **del, void (*predel)(Avl*, void*), void *arg)
1749a747e4fSDavid du Colombier {
1759a747e4fSDavid du Colombier int i, ob;
1769a747e4fSDavid du Colombier Avl *r, *or;
1779a747e4fSDavid du Colombier
1789a747e4fSDavid du Colombier if(*tp == nil)
1799a747e4fSDavid du Colombier return 0;
1809a747e4fSDavid du Colombier
1819a747e4fSDavid du Colombier ob = (*tp)->bal;
182*2ecc4774SDavid du Colombier if((i=canoncmp(cmp(rx, *tp))) != 0){
1839a747e4fSDavid du Colombier (*tp)->bal += i*_deleteavl(&(*tp)->n[(i+1)/2], *tp, rx, cmp, del, predel, arg);
1849a747e4fSDavid du Colombier balance(tp, p);
1859a747e4fSDavid du Colombier return -(ob!=0 && (*tp)->bal==0);
1869a747e4fSDavid du Colombier }
1879a747e4fSDavid du Colombier
1889a747e4fSDavid du Colombier if(predel)
1899a747e4fSDavid du Colombier (*predel)(*tp, arg);
1909a747e4fSDavid du Colombier
1919a747e4fSDavid du Colombier or = *tp;
1929a747e4fSDavid du Colombier if(or->n[i=0]==nil || or->n[i=1]==nil){
1939a747e4fSDavid du Colombier *tp = or->n[1-i];
1949a747e4fSDavid du Colombier if(*tp)
1959a747e4fSDavid du Colombier (*tp)->p = p;
1969a747e4fSDavid du Colombier *del = or;
1979a747e4fSDavid du Colombier return -1;
1989a747e4fSDavid du Colombier }
1999a747e4fSDavid du Colombier
2009a747e4fSDavid du Colombier /* deleting node with two kids, find successor */
2019a747e4fSDavid du Colombier or->bal += successor(&or->n[1], or, &r);
2029a747e4fSDavid du Colombier r->bal = or->bal;
2039a747e4fSDavid du Colombier r->n[0] = or->n[0];
2049a747e4fSDavid du Colombier r->n[1] = or->n[1];
2059a747e4fSDavid du Colombier *tp = r;
2069a747e4fSDavid du Colombier (*tp)->p = p;
2079a747e4fSDavid du Colombier /* node has changed; fix children's parent pointers */
2089a747e4fSDavid du Colombier if(r->n[0])
2099a747e4fSDavid du Colombier r->n[0]->p = r;
2109a747e4fSDavid du Colombier if(r->n[1])
2119a747e4fSDavid du Colombier r->n[1]->p = r;
2129a747e4fSDavid du Colombier *del = or;
2139a747e4fSDavid du Colombier balance(tp, p);
2149a747e4fSDavid du Colombier return -(ob!=0 && (*tp)->bal==0);
2159a747e4fSDavid du Colombier }
2169a747e4fSDavid du Colombier
2179a747e4fSDavid du Colombier static void
checkparents(Avl * a,Avl * p)2189a747e4fSDavid du Colombier checkparents(Avl *a, Avl *p)
2199a747e4fSDavid du Colombier {
2209a747e4fSDavid du Colombier if(a==nil)
2219a747e4fSDavid du Colombier return;
2229a747e4fSDavid du Colombier if(a->p != p)
2239a747e4fSDavid du Colombier print("bad parent\n");
2249a747e4fSDavid du Colombier checkparents(a->n[0], a);
2259a747e4fSDavid du Colombier checkparents(a->n[1], a);
2269a747e4fSDavid du Colombier }
2279a747e4fSDavid du Colombier
2289a747e4fSDavid du Colombier struct Avltree
2299a747e4fSDavid du Colombier {
2309a747e4fSDavid du Colombier Avl *root;
2319a747e4fSDavid du Colombier int (*cmp)(Avl*, Avl*);
2329a747e4fSDavid du Colombier Avlwalk *walks;
2339a747e4fSDavid du Colombier };
2349a747e4fSDavid du Colombier struct Avlwalk
2359a747e4fSDavid du Colombier {
2369a747e4fSDavid du Colombier int started;
237867bfcc6SDavid du Colombier int moved;
2389a747e4fSDavid du Colombier Avlwalk *next;
2399a747e4fSDavid du Colombier Avltree *tree;
2409a747e4fSDavid du Colombier Avl *node;
2419a747e4fSDavid du Colombier };
2429a747e4fSDavid du Colombier
2439a747e4fSDavid du Colombier
2449a747e4fSDavid du Colombier Avltree*
mkavltree(int (* cmp)(Avl *,Avl *))2459a747e4fSDavid du Colombier mkavltree(int (*cmp)(Avl*, Avl*))
2469a747e4fSDavid du Colombier {
2479a747e4fSDavid du Colombier Avltree *t;
2489a747e4fSDavid du Colombier
2499a747e4fSDavid du Colombier t = emalloc(sizeof(*t));
2509a747e4fSDavid du Colombier t->cmp = cmp;
2519a747e4fSDavid du Colombier return t;
2529a747e4fSDavid du Colombier }
2539a747e4fSDavid du Colombier
2549a747e4fSDavid du Colombier void
insertavl(Avltree * t,Avl * new,Avl ** oldp)2559a747e4fSDavid du Colombier insertavl(Avltree *t, Avl *new, Avl **oldp)
2569a747e4fSDavid du Colombier {
2579a747e4fSDavid du Colombier *oldp = nil;
2589a747e4fSDavid du Colombier _insertavl(&t->root, nil, new, t->cmp, oldp);
2599a747e4fSDavid du Colombier }
2609a747e4fSDavid du Colombier
2619a747e4fSDavid du Colombier Avl*
lookupavl(Avltree * t,Avl * key)2629a747e4fSDavid du Colombier lookupavl(Avltree *t, Avl *key)
2639a747e4fSDavid du Colombier {
2649a747e4fSDavid du Colombier return _lookupavl(t->root, key, t->cmp);
2659a747e4fSDavid du Colombier }
2669a747e4fSDavid du Colombier
2679a747e4fSDavid du Colombier static Avl*
findpredecessor(Avl * a)2689a747e4fSDavid du Colombier findpredecessor(Avl *a)
2699a747e4fSDavid du Colombier {
2709a747e4fSDavid du Colombier
2719a747e4fSDavid du Colombier if(a == nil)
272867bfcc6SDavid du Colombier return nil;
273867bfcc6SDavid du Colombier
274867bfcc6SDavid du Colombier if(a->n[0] != nil){
275867bfcc6SDavid du Colombier /* predecessor is rightmost descendant of left child */
276867bfcc6SDavid du Colombier for(a=a->n[0]; a->n[1]; a=a->n[1])
277867bfcc6SDavid du Colombier ;
2789a747e4fSDavid du Colombier return a;
279867bfcc6SDavid du Colombier }else{
280867bfcc6SDavid du Colombier /* we're at a leaf, successor is a parent we enter from the right */
281867bfcc6SDavid du Colombier while(a->p && a->p->n[0]==a)
282867bfcc6SDavid du Colombier a = a->p;
283867bfcc6SDavid du Colombier return a->p;
284867bfcc6SDavid du Colombier }
2859a747e4fSDavid du Colombier }
2869a747e4fSDavid du Colombier
2879a747e4fSDavid du Colombier static Avl*
findsuccessor(Avl * a)288867bfcc6SDavid du Colombier findsuccessor(Avl *a)
2899a747e4fSDavid du Colombier {
2909a747e4fSDavid du Colombier
291867bfcc6SDavid du Colombier if(a == nil)
292867bfcc6SDavid du Colombier return nil;
293867bfcc6SDavid du Colombier
294867bfcc6SDavid du Colombier if(a->n[1] != nil){
295867bfcc6SDavid du Colombier /* successor is leftmost descendant of right child */
296867bfcc6SDavid du Colombier for(a=a->n[1]; a->n[0]; a=a->n[0])
297867bfcc6SDavid du Colombier ;
298867bfcc6SDavid du Colombier return a;
299867bfcc6SDavid du Colombier }else{
300867bfcc6SDavid du Colombier /* we're at a leaf, successor is a parent we enter from the left going up */
301867bfcc6SDavid du Colombier while(a->p && a->p->n[1] == a)
3029a747e4fSDavid du Colombier a = a->p;
303867bfcc6SDavid du Colombier return a->p;
3049a747e4fSDavid du Colombier }
3059a747e4fSDavid du Colombier }
3069a747e4fSDavid du Colombier
3079a747e4fSDavid du Colombier static void
walkdel(Avl * a,void * v)3089a747e4fSDavid du Colombier walkdel(Avl *a, void *v)
3099a747e4fSDavid du Colombier {
3109a747e4fSDavid du Colombier Avl *p;
3119a747e4fSDavid du Colombier Avlwalk *w;
3129a747e4fSDavid du Colombier Avltree *t;
3139a747e4fSDavid du Colombier
3149a747e4fSDavid du Colombier if(a == nil)
3159a747e4fSDavid du Colombier return;
3169a747e4fSDavid du Colombier
3179a747e4fSDavid du Colombier p = findpredecessor(a);
3189a747e4fSDavid du Colombier t = v;
3199a747e4fSDavid du Colombier for(w=t->walks; w; w=w->next){
3209a747e4fSDavid du Colombier if(w->node == a){
3219a747e4fSDavid du Colombier /* back pointer to predecessor; not perfect but adequate */
322867bfcc6SDavid du Colombier w->moved = 1;
3239a747e4fSDavid du Colombier w->node = p;
3249a747e4fSDavid du Colombier if(p == nil)
3259a747e4fSDavid du Colombier w->started = 0;
3269a747e4fSDavid du Colombier }
3279a747e4fSDavid du Colombier }
3289a747e4fSDavid du Colombier }
3299a747e4fSDavid du Colombier
3309a747e4fSDavid du Colombier void
deleteavl(Avltree * t,Avl * key,Avl ** oldp)3319a747e4fSDavid du Colombier deleteavl(Avltree *t, Avl *key, Avl **oldp)
3329a747e4fSDavid du Colombier {
3339a747e4fSDavid du Colombier *oldp = nil;
3349a747e4fSDavid du Colombier _deleteavl(&t->root, nil, key, t->cmp, oldp, walkdel, t);
3359a747e4fSDavid du Colombier }
3369a747e4fSDavid du Colombier
3379a747e4fSDavid du Colombier Avlwalk*
avlwalk(Avltree * t)3389a747e4fSDavid du Colombier avlwalk(Avltree *t)
3399a747e4fSDavid du Colombier {
3409a747e4fSDavid du Colombier Avlwalk *w;
3419a747e4fSDavid du Colombier
3429a747e4fSDavid du Colombier w = emalloc(sizeof(*w));
3439a747e4fSDavid du Colombier w->tree = t;
3449a747e4fSDavid du Colombier w->next = t->walks;
3459a747e4fSDavid du Colombier t->walks = w;
3469a747e4fSDavid du Colombier return w;
3479a747e4fSDavid du Colombier }
3489a747e4fSDavid du Colombier
3499a747e4fSDavid du Colombier Avl*
avlnext(Avlwalk * w)3509a747e4fSDavid du Colombier avlnext(Avlwalk *w)
3519a747e4fSDavid du Colombier {
3529a747e4fSDavid du Colombier Avl *a;
3539a747e4fSDavid du Colombier
3549a747e4fSDavid du Colombier if(w->started==0){
3559a747e4fSDavid du Colombier for(a=w->tree->root; a && a->n[0]; a=a->n[0])
3569a747e4fSDavid du Colombier ;
3579a747e4fSDavid du Colombier w->node = a;
3589a747e4fSDavid du Colombier w->started = 1;
3599a747e4fSDavid du Colombier }else{
360867bfcc6SDavid du Colombier a = findsuccessor(w->node);
361867bfcc6SDavid du Colombier if(a == w->node)
3629a747e4fSDavid du Colombier abort();
363867bfcc6SDavid du Colombier w->node = a;
3649a747e4fSDavid du Colombier }
365867bfcc6SDavid du Colombier return w->node;
366867bfcc6SDavid du Colombier }
367867bfcc6SDavid du Colombier
368867bfcc6SDavid du Colombier Avl*
avlprev(Avlwalk * w)369867bfcc6SDavid du Colombier avlprev(Avlwalk *w)
370867bfcc6SDavid du Colombier {
371867bfcc6SDavid du Colombier Avl *a;
372867bfcc6SDavid du Colombier
373867bfcc6SDavid du Colombier if(w->started == 0){
374867bfcc6SDavid du Colombier for(a=w->tree->root; a && a->n[1]; a=a->n[1])
375867bfcc6SDavid du Colombier ;
376867bfcc6SDavid du Colombier w->node = a;
377867bfcc6SDavid du Colombier w->started = 1;
378867bfcc6SDavid du Colombier }else if(w->moved){
379867bfcc6SDavid du Colombier w->moved = 0;
380867bfcc6SDavid du Colombier return w->node;
381867bfcc6SDavid du Colombier }else{
382867bfcc6SDavid du Colombier a = findpredecessor(w->node);
383867bfcc6SDavid du Colombier if(a == w->node)
384867bfcc6SDavid du Colombier abort();
3859a747e4fSDavid du Colombier w->node = a;
3869a747e4fSDavid du Colombier }
3879a747e4fSDavid du Colombier return w->node;
3889a747e4fSDavid du Colombier }
3899a747e4fSDavid du Colombier
3909a747e4fSDavid du Colombier void
endwalk(Avlwalk * w)3919a747e4fSDavid du Colombier endwalk(Avlwalk *w)
3929a747e4fSDavid du Colombier {
3939a747e4fSDavid du Colombier Avltree *t;
3949a747e4fSDavid du Colombier Avlwalk **l;
3959a747e4fSDavid du Colombier
3969a747e4fSDavid du Colombier t = w->tree;
3979a747e4fSDavid du Colombier for(l=&t->walks; *l; l=&(*l)->next){
3989a747e4fSDavid du Colombier if(*l == w){
3999a747e4fSDavid du Colombier *l = w->next;
4009a747e4fSDavid du Colombier break;
4019a747e4fSDavid du Colombier }
4029a747e4fSDavid du Colombier }
4039a747e4fSDavid du Colombier free(w);
4049a747e4fSDavid du Colombier }
4059a747e4fSDavid du Colombier
4069a747e4fSDavid du Colombier static void
walkavl(Avl * t,void (* f)(Avl *,void *),void * v)4079a747e4fSDavid du Colombier walkavl(Avl *t, void (*f)(Avl*, void*), void *v)
4089a747e4fSDavid du Colombier {
4099a747e4fSDavid du Colombier if(t == nil)
4109a747e4fSDavid du Colombier return;
4119a747e4fSDavid du Colombier walkavl(t->n[0], f, v);
4129a747e4fSDavid du Colombier f(t, v);
4139a747e4fSDavid du Colombier walkavl(t->n[1], f, v);
4149a747e4fSDavid du Colombier }
4159a747e4fSDavid du Colombier
416