libavl: lookup can return the closest match
This commit is contained in:
parent
f2b7f24e4e
commit
9cf5198145
9 changed files with 34 additions and 25 deletions
|
@ -15,8 +15,9 @@ struct Avltree {
|
||||||
Avl *root;
|
Avl *root;
|
||||||
};
|
};
|
||||||
|
|
||||||
Avltree *avlcreate(int(*cmp)(Avl*, Avl*));
|
Avltree *avlinit(Avltree*, int(*)(Avl*, Avl*));
|
||||||
Avl *avllookup(Avltree*, Avl*);
|
Avltree *avlcreate(int(*)(Avl*, Avl*));
|
||||||
|
Avl *avllookup(Avltree*, Avl*, int);
|
||||||
Avl *avldelete(Avltree*, Avl*);
|
Avl *avldelete(Avltree*, Avl*);
|
||||||
Avl *avlinsert(Avltree*, Avl*);
|
Avl *avlinsert(Avltree*, Avl*);
|
||||||
Avl *avlnext(Avl*);
|
Avl *avlnext(Avl*);
|
||||||
|
|
|
@ -30,7 +30,7 @@ struct Avltree {
|
||||||
Avltree *avlcreate(int(*cmp)(Avl*, Avl*));
|
Avltree *avlcreate(int(*cmp)(Avl*, Avl*));
|
||||||
Avl *avlinsert(Avltree *tree, Avl *new);
|
Avl *avlinsert(Avltree *tree, Avl *new);
|
||||||
Avl *avldelete(Avltree *tree, Avl *key);
|
Avl *avldelete(Avltree *tree, Avl *key);
|
||||||
Avl *avllookup(Avltree *tree, Avl *key);
|
Avl *avllookup(Avltree *tree, Avl *key, int dir);
|
||||||
Avl *avlnext(Avl *n);
|
Avl *avlnext(Avl *n);
|
||||||
Avl *avlprev(Avl *n);
|
Avl *avlprev(Avl *n);
|
||||||
|
|
||||||
|
@ -55,13 +55,15 @@ node into the tree and returns an existing
|
||||||
node with the same key that has been removed
|
node with the same key that has been removed
|
||||||
from the tree and may be freed.
|
from the tree and may be freed.
|
||||||
.I Avllookup
|
.I Avllookup
|
||||||
returns the
|
searches for a given key and returns
|
||||||
node that matches the key or
|
the closest node less than the given key,
|
||||||
.B nil
|
.BR nil ,
|
||||||
if no node matches.
|
or the closest node greater than the key depending on whether
|
||||||
|
.I dir
|
||||||
|
is less than, equal to, or greater than zero, respectively.
|
||||||
.I Avldelete
|
.I Avldelete
|
||||||
removes the node matching the key from the tree and returns
|
removes the node matching the key from the tree and returns
|
||||||
it. It returns nil of no matching key is found.
|
it. It returns nil if no matching key is found.
|
||||||
.PP
|
.PP
|
||||||
.I Avlnext
|
.I Avlnext
|
||||||
returns the next
|
returns the next
|
||||||
|
|
|
@ -22,7 +22,7 @@ mtreeisdup(Mailbox *mb, Message *m)
|
||||||
return 0;
|
return 0;
|
||||||
memset(&t, 0, sizeof t);
|
memset(&t, 0, sizeof t);
|
||||||
t.m = m;
|
t.m = m;
|
||||||
if(avllookup(mb->mtree, &t))
|
if(avllookup(mb->mtree, &t, 0))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ mtreefind(Mailbox *mb, uchar *digest)
|
||||||
m0.digest = digest;
|
m0.digest = digest;
|
||||||
memset(&t, 0, sizeof t);
|
memset(&t, 0, sizeof t);
|
||||||
t.m = &m0;
|
t.m = &m0;
|
||||||
if(p = (Mtree*)avllookup(mb->mtree, &t))
|
if(p = (Mtree*)avllookup(mb->mtree, &t, 0))
|
||||||
return p->m;
|
return p->m;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ mtreedelete(Mailbox *mb, Message *m)
|
||||||
if(m->deleted & ~Deleted){
|
if(m->deleted & ~Deleted){
|
||||||
if(m->digest == nil)
|
if(m->digest == nil)
|
||||||
return;
|
return;
|
||||||
p = (Mtree*)avllookup(mb->mtree, &t);
|
p = (Mtree*)avllookup(mb->mtree, &t, 0);
|
||||||
if(p == nil || p->m != m)
|
if(p == nil || p->m != m)
|
||||||
return;
|
return;
|
||||||
p = (Mtree*)avldelete(mb->mtree, &t);
|
p = (Mtree*)avldelete(mb->mtree, &t);
|
||||||
|
|
|
@ -25,7 +25,7 @@ fstreefind(Box *mb, int id)
|
||||||
memset(&t, 0, sizeof t);
|
memset(&t, 0, sizeof t);
|
||||||
m0.id = id;
|
m0.id = id;
|
||||||
t.m = &m0;
|
t.m = &m0;
|
||||||
if(p = (Fstree*)avllookup(mb->fstree, &t))
|
if(p = (Fstree*)avllookup(mb->fstree, &t, 0))
|
||||||
return p->m;
|
return p->m;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ rdimp(Biobuf *b, Box *box)
|
||||||
memset(&t, 0, sizeof t);
|
memset(&t, 0, sizeof t);
|
||||||
m0.info[Idigest] = f[0];
|
m0.info[Idigest] = f[0];
|
||||||
t.m = &m0;
|
t.m = &m0;
|
||||||
p = (Mtree*)avllookup(mtree, &t);
|
p = (Mtree*)avllookup(mtree, &t, 0);
|
||||||
if(p){
|
if(p){
|
||||||
m = p->m;
|
m = p->m;
|
||||||
if(m->uid && m->uid != u){
|
if(m->uid && m->uid != u){
|
||||||
|
|
|
@ -51,7 +51,7 @@ havevisited(uchar score[VtScoreSize], int type)
|
||||||
return 0;
|
return 0;
|
||||||
memmove(a.score, score, VtScoreSize);
|
memmove(a.score, score, VtScoreSize);
|
||||||
a.type = type;
|
a.type = type;
|
||||||
return avllookup(scoretree, &a) != nil;
|
return avllookup(scoretree, &a, 0) != nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
int extraproc = -1, throttle;
|
int extraproc = -1, throttle;
|
||||||
|
|
||||||
static QLock* golock;
|
static QLock *golock;
|
||||||
static Rendez* gorend;
|
static Rendez *gorend;
|
||||||
static int* go;
|
static int *go;
|
||||||
|
|
||||||
static QLock runninglock;
|
static QLock runninglock;
|
||||||
static Rendez runningrend;
|
static Rendez runningrend;
|
||||||
|
|
|
@ -413,7 +413,7 @@ sym(char *name)
|
||||||
Sym *s, l;
|
Sym *s, l;
|
||||||
|
|
||||||
l.name = name;
|
l.name = name;
|
||||||
s = (Sym*)avllookup(syms, &l);
|
s = (Sym*)avllookup(syms, &l, 0);
|
||||||
if(s != nil)
|
if(s != nil)
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,6 @@
|
||||||
|
|
||||||
/* See Knuth Volume 3, 6.2.3 */
|
/* See Knuth Volume 3, 6.2.3 */
|
||||||
|
|
||||||
Avl *avllookup(Avltree*, Avl*);
|
|
||||||
Avl *avldelete(Avltree*, Avl*);
|
|
||||||
Avl *avlinsert(Avltree*, Avl*);
|
|
||||||
|
|
||||||
Avltree*
|
Avltree*
|
||||||
avlcreate(int (*cmp)(Avl*, Avl*))
|
avlcreate(int (*cmp)(Avl*, Avl*))
|
||||||
{
|
{
|
||||||
|
@ -16,32 +12,42 @@ avlcreate(int (*cmp)(Avl*, Avl*))
|
||||||
t = malloc(sizeof(*t));
|
t = malloc(sizeof(*t));
|
||||||
if(t == nil)
|
if(t == nil)
|
||||||
return nil;
|
return nil;
|
||||||
|
return avlinit(t, cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Avltree*
|
||||||
|
avlinit(Avltree *t, int (*cmp)(Avl*, Avl*))
|
||||||
|
{
|
||||||
t->cmp = cmp;
|
t->cmp = cmp;
|
||||||
t->root = nil;
|
t->root = nil;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
Avl*
|
Avl*
|
||||||
avllookup(Avltree *t, Avl *k)
|
avllookup(Avltree *t, Avl *k, int d)
|
||||||
{
|
{
|
||||||
Avl *h;
|
Avl *h, *n;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
n = nil;
|
||||||
h = t->root;
|
h = t->root;
|
||||||
while(h != nil){
|
while(h != nil){
|
||||||
c = (t->cmp)(k, h);
|
c = (t->cmp)(k, h);
|
||||||
if(c < 0){
|
if(c < 0){
|
||||||
|
if(d > 0)
|
||||||
|
n = h;
|
||||||
h = h->c[0];
|
h = h->c[0];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(c > 0){
|
if(c > 0){
|
||||||
|
if(d < 0)
|
||||||
|
n = h;
|
||||||
h = h->c[1];
|
h = h->c[1];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
return nil;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int insert(int (*)(Avl*, Avl*), Avl*, Avl**, Avl*, Avl**);
|
static int insert(int (*)(Avl*, Avl*), Avl*, Avl**, Avl*, Avl**);
|
||||||
|
|
Loading…
Reference in a new issue