xref: /plan9/sys/src/cmd/replica/avl.c (revision 2ecc4774c0672e9bf5220b40ff89393ea3ca436c)
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