Beispiel #1
0
static LTI *aa_find(LTI **t,char *name,int len,int *insert) { // find/insert node into t
    LTI *lti=NULL;
    int iter=(*insert)&ITER;
    int dir=(*insert)&1;
    if ((*t)==&aa_sentinel)
        lti=((*insert)&INSERT)?(*t)=LTI_init(NEW(LTI),name,len):NULL;
    else {
        int delta=0;
        for (int i=0;delta==0 && i<PREVIEWLEN && i<len && i<(*t)->len;i++)
            delta=name[i]-(*t)->preview[i];
        if (!delta) // preview matched, compare full strings
            delta=strnncmp(name,len,(*t)->name,(*t)->len);
        int deltadir=delta<0?LEFT:RIGHT; // turn LTZ/Z/GTZ into left/right/right
        if (delta) {
            if (LTI_invalid(lti=aa_find(&(*t)->lnk[deltadir],name,len,insert)) && iter && dir!=deltadir)
                lti=*t;
        }
        else if (iter) // matches, but find next smaller/larger
            lti=aa_most((*t)->lnk[dir],!dir);
        else // return match
            lti=(*t),(*insert)=0;
    }
    if ((*insert)&INSERT) { // rebalance if necessary
        aa_skew(t);
        aa_split(t);
    }
    return lti;
}
Beispiel #2
0
// remove is non-aa-canonical...
// a: traverse down to leaf, looking for matches along the way
// b: if there's a match, clip leaf and return thru to matching node
// c: matching node swaps, and then returns matching node to caller
static LTI *aa_remove(LTI **t,char *name,int len,int match) {
    LTI *result=NULL;

    if (LTI_invalid(*t))
        return &aa_sentinel;

    // descend tree, finding matching node ("toremove") and then "next-greater" leaf ("tokeep")
    int delta=0;
    for (int i=0;delta==0 && i<PREVIEWLEN && i<len && i<(*t)->len;i++)
        delta=name[i]-(*t)->preview[i];
    if (!delta) // preview matched, compare full strings
        delta=strnncmp(name,len,(*t)->name,(*t)->len);
    result=aa_remove(&(*t)->lnk[delta<0?LEFT:RIGHT],name,len,match|!delta);

    if (!delta) { // matching node
        if (result!=&aa_sentinel) { // swap with leaf...
            result->lnk[LEFT]=(*t)->lnk[LEFT];
            result->lnk[RIGHT]=(*t)->lnk[RIGHT];
            (*t)->lnk[LEFT]=&aa_sentinel;
            (*t)->lnk[RIGHT]=&aa_sentinel;
        }
        LTI *newresult=(*t);
        (*t)=result;
        result=newresult;
    } else if (match && result==&aa_sentinel) {
        result=*t;
        *t=&aa_sentinel;
    }

 cleanup:
    // on the way back, re rebalance
    if (!LTI_invalid(*t)) {
        if (((*t)->lnk[LEFT]->level < ((*t)->level-1)) || ((*t)->lnk[RIGHT]->level < ((*t)->level-1))) {
            (*t)->level--;
            if ((*t)->lnk[RIGHT]->level > (*t)->level)
                (*t)->lnk[RIGHT]->level = (*t)->level;
            aa_skew(t);
            aa_skew(&(*t)->lnk[RIGHT]);
            aa_skew(&(*t)->lnk[RIGHT]->lnk[RIGHT]);
            aa_split(t);
            aa_split(&(*t)->lnk[RIGHT]);
        }
    }

 done:
    return result;
}
Beispiel #3
0
static aa_node *
aa_delete_r(aa_tree *tree, aa_node **nodep, void *key)
{
	aa_node *node, *pred, *succ;
	void *ret;
	int cmp;

	ret = NULL;
	if ((node = *nodep) == &aa_nil) {
		return (NULL);
	} else if ((cmp = tree->compare(key, node->data)) == 0) {
		if (node->left == &aa_nil && node->right == &aa_nil) {
			ret = node->data;
			aa_free(node);
			*nodep = &aa_nil;
			tree->size--;
			return (ret);
		} else if (node->left == &aa_nil) {
			succ = node->right;
			while (succ->left != &aa_nil)
				succ = succ->left;
			node->data = succ->data;
			ret = aa_delete_r(tree, &node->right, succ->data);
		} else {
			pred = node->left;
			while (pred->right != &aa_nil)
				pred = pred->right;
			node->data = pred->data;
			ret = aa_delete_r(tree, &node->left, pred->data);
		}
	} else if (cmp < 0) {
		ret = aa_delete_r(tree, &node->left, key);
	} else /* (cmp > 0) */ {
		ret = aa_delete_r(tree, &node->right, key);
	}
	if (node->left->level < node->level - 1 ||
	    node->right->level < node->level - 1)
		node->level = node->level - 1;
	node = aa_skew(node);
	node->right = aa_skew(node->right);
	node->right->right = aa_skew(node->right->right);
	node = aa_split(node);
	node->right = aa_split(node->right);
	*nodep = node;
	return (ret);
}