#include #include #include #include "bstimpl.h" /* See Sedgewick 'Left-leaning Red-Black Trees' */ static Bst *llrblookup(Bsttree*, Bst*); static Bst *llrbdelete(Bsttree*, Bst*); static Bst *llrbinsert(Bsttree*, Bst*); Bsttree* bstcreatellrb(int (*cmp)(Bst*, Bst*)) { Bsttree *t; t = malloc(sizeof(*t)); if(t == nil) return nil; t->cmp = cmp; t->root = nil; t->lookup = llrblookup; t->delete = llrbdelete; t->insert = llrbinsert; return t; } enum { RED, BLACK }; #define isred(h) ((h) == nil ? 0 : (h)->color == RED) static Bst* llrblookup(Bsttree *t, Bst *k) { Bst *h; int c; h = t->root; while(h != nil){ assert(!isred(h->c[1])); assert(!isred(h->c[0]) || !isred(h->c[0]->c[0])); c = (t->cmp)(k, h); if(c < 0){ h = h->c[0]; continue; } if(c > 0){ h = h->c[1]; continue; } return h; } return nil; } static Bst *insert(int(*)(Bst*, Bst*), Bst*, Bst*, Bst**); static Bst* llrbinsert(Bsttree *t, Bst *n) { Bst *op; if(n == nil) return nil; op = nil; t->root = insert(t->cmp, t->root, n, &op); t->root->color = BLACK; return op; } static Bst *flip(Bst*); static Bst *rotate(int, Bst*); static Bst* insert(int (*cmp)(Bst*, Bst*), Bst *h, Bst *n, Bst **op) { int c; if(h == nil) { n->c[0] = n->c[1] = nil; n->color = RED; return n; } c = cmp(n, h); if(c == 0) { *op = h; *n = *h; h = n; } else if(c < 0) h->c[0] = insert(cmp, h->c[0], n, op); else h->c[1] = insert(cmp, h->c[1], n, op); if(isred(h->c[0]) && isred(h->c[1])) flip(h); else if(isred(h->c[0]) && isred(h->c[0]->c[0])) h = flip(rotate(0, h)); else if(isred(h->c[1])) h = rotate(1, h); return h; } static Bst *delete(int(*)(Bst*, Bst*), Bst*, Bst*, Bst**); static Bst* llrbdelete(Bsttree *t, Bst *n) { Bst *op; op = nil; t->root = delete(t->cmp, t->root, n, &op); if(t->root != nil) t->root->color = BLACK; return op; } static Bst *moveredleft(Bst*); static Bst *moveredright(Bst*); static Bst *deletemin(Bst*, Bst**); static Bst* delete(int (*cmp)(Bst*, Bst*), Bst *h, Bst *n, Bst **delp) { Bst *e; if(h == nil) return nil; if(cmp(n, h) < 0) { if(h->c[0] == nil) return h; if(!isred(h->c[0]) && !isred(h->c[0]->c[0])) h = moveredleft(h); h->c[0] = delete(cmp, h->c[0], n, delp); if(isred(h->c[0]) && isred(h->c[1])) flip(h); else if(isred(h->c[1])) h = rotate(1, h); return h; } if(isred(h->c[0])) h = rotate(0, h); if(h->c[1] == nil) { if(cmp(n, h) == 0) { assert(isred(h)); *delp = h; return nil; } return h; } if(!isred(h->c[1]) && !isred(h->c[1]->c[0])) h = moveredright(h); if(cmp(n, h) == 0) { *delp = h; h->c[1] = deletemin(h->c[1], &e); *e = *h; h = e; } else h->c[1] = delete(cmp, h->c[1], n, delp); if(isred(h->c[0]) && isred(h->c[1])) flip(h); else if(isred(h->c[1])) h = rotate(1, h); return h; } static Bst* deletemin(Bst *h, Bst **op) { if(h->c[0] == nil) { assert(isred(h)); *op = h; return nil; } if(!isred(h->c[0]) && !isred(h->c[0]->c[0])) h = moveredleft(h); h->c[0] = deletemin(h->c[0], op); if(isred(h->c[0]) && isred(h->c[1])) flip(h); else if(isred(h->c[1])) h = rotate(1, h); return h; } static Bst* rotate(int a, Bst *h) { Bst *x; assert(isred(h->c[a])); x = h->c[a]; h->c[a] = x->c[a^1]; x->c[a^1] = h; x->color = h->color; h->color = RED; return x; } static Bst* flip(Bst *h) { assert(h->c[0]->color == h->c[1]->color); h->color ^= 1; h->c[0]->color ^= 1; h->c[1]->color ^= 1; return h; } static Bst* moveredleft(Bst *h) { flip(h); if(isred(h->c[1]->c[0])){ h->c[1] = rotate(0, h->c[1]); h = rotate(1, h); flip(h); } return h; } static Bst* moveredright(Bst *h) { flip(h); if(isred(h->c[0]->c[0])){ h = rotate(0, h); flip(h); } return h; }