Exemplo n.º 1
0
/*  Algorithm T of Knuth 6.2.2.2
    key is pointer to a user data area containing the key
    and possibly more.

    We iterate like Knuth does, but using for(;;) instead
    of go-to.  */
static struct ts_entry *
tsearch_inner( const void *key, struct ts_entry* localrootp,
    int (*compar)(const void *, const void *),
    int*inserted)
{
    struct ts_entry* p = localrootp;
    for(;;) {
        struct ts_entry *r = 0;
        /* T2. */
        int kc = compar(key,p->keyptr);
        if(kc < 0) {
            /* T3. */
            struct ts_entry *l = p->llink;
            if (l) {
                p = l;
                continue;
            }
            /* T5 */
            r = tsearch_inner_do_insert(key,kc,inserted,p);
            return r;
        } else if (kc > 0 ) {
            /* T4. */
            struct ts_entry *r2 = p->rlink;
            if (r2) {
                p = r2;
                continue;
            }
            /* T5 */
            r =  tsearch_inner_do_insert(key,kc,inserted,p);
            return r;
        }
        /* K = KEY(P) in Knuth. */
        /* kc == 0, we found the entry we search for. */
        return p;
    }
    /* Can never get here. */
    return 0;
}
Exemplo n.º 2
0
/* Algorithm A of Knuth 6.2.3, balanced tree.
   key is pointer to a user data area containing the key
   and possibly more.

   We could recurse on this routine, but instead we
   iterate (like Knuth does, but using for(;;) instead
   of go-to.

  */
static struct ts_entry *
tsearch_inner( const void *key, struct ts_entry* head,
    int (*compar)(const void *, const void *),
    int*inserted,
    struct ts_entry **nullme,
    int * comparres)
{
    /* t points to parent of p */
    struct ts_entry *t = head;
    /* p moves down tree, p starts as root. */
    struct ts_entry *p = head->rlink;
    /* s points where rebalancing may be needed. */
    struct ts_entry *s = p;
    struct ts_entry *r = 0;
    struct ts_entry *q = 0;

    int a = 0;
    int kc = 0;
    for(;;) {
        /* A2. */
        kc = compar(key,p->keyptr);
        if(kc) {
            /* A3 and A4 handled here. */
            q = getlink(p,kc);
            if(!q) {
                /* Does step A5. */
                q = tsearch_inner_do_insert(key,kc,inserted,p);
                if (!q) {
                    /*  Out of memory. */
                    return q;
                }
                break; /* to A5. */
            }
            if(q->balance) {
                t = p;
                s = q;
            }
            p = q;
            continue;
        }
        /* K = KEY(P) in Knuth. */
        /* kc == 0, we found the entry we search for. */
        return p;
    }
    /* A5:  work already done. */

    /* A6: */
    {
        /*  Balance factors on nodes betwen S and Q need to be
            changed from zero to +-1  */
        int kc2 = compar(key,s->keyptr);
        if (kc2 < 0) {
            a = -1;
        } else {
            a = 1;
        }
        r = p = getlink(s,a);
        while (p != q) {
            int kc3 = compar(key,p->keyptr);
            if(kc3 < 0) {
                p->balance = -1;
                p = p->llink;
            } else if (kc3 > 0) {
                p->balance = 1;
                p = p->rlink;
            } else {
                /* ASSERT: p == q */
                break;
            }
        }
    }

    /* A7: */
    {
        if(! s->balance) {
            /* Tree has grown higher. */
            s->balance = a;
            /* Counting in pointers, not integers. Ugh. */
            head->llink  = head->llink + 1;
            return q;
        }
        if(s->balance == -a) {
            /* Tree is more balanced */
            s->balance = 0;
            return q;
        }
        if (s->balance == a) {
            /* Rebalance. */
            if(r->balance == a) {
                /* single rotation, step A8. */
                p = r;
                setlink(s,a,getlink(r,-a));
                setlink(r,-a,s);
                s->balance = 0;
                r->balance = 0;
            } else if (r->balance == -a) {
                /* double rotation, step A9. */
                p = getlink(r,-a);
                setlink(r,-a,getlink(p,a));
                setlink(p,a,r);
                setlink(s,a,getlink(p,-a));
                setlink(p,-a,s);
                if(p->balance == a) {
                    s->balance = -a;
                    r->balance = 0;
                } else if (p->balance  == 0) {
                    s->balance = 0;
                    r->balance = 0;
                } else if (p->balance == -a) {
                    s->balance = 0;
                    r->balance = a;
                }
                p->balance = 0;
            } else {
                fprintf(stderr,"Impossible balanced tree situation!\n");
                /* Impossible. Cannot be here. */
                exit(1);
            }
        } else {
            fprintf(stderr,"Impossible balanced tree situation!!\n");
            /* Impossible. Cannot be here. */
            exit(1);
        }
    }

    /* A10: */
    if (s == t->rlink) {
        t->rlink = p;
    } else {
        t->llink = p;
    }
#ifdef DW_CHECK_CONSISTENCY
    dwarf_check_balance(head,1);
#endif
    return q;
}