/* Deletes from |tree| and returns an item matching |item|. Returns a null pointer if no matching item found. */ void * bst_delete (struct bst_table *tree, const void *item) { struct bst_node *p, *q; /* Node to delete and its parent. */ int cmp; /* Comparison between |p->bst_data| and |item|. */ int dir; /* Side of |q| on which |p| is located. */ assert (tree != NULL && item != NULL); p = (struct bst_node *) &tree->bst_root; for (cmp = -1; cmp != 0; cmp = tree->bst_compare (item, p->bst_data, tree->bst_param)) { dir = cmp > 0; q = p; p = p->bst_link[dir]; if (p == NULL) return NULL; } item = p->bst_data; if (p->bst_link[1] == NULL) q->bst_link[dir] = p->bst_link[0]; else { struct bst_node *r = p->bst_link[1]; if (r->bst_link[0] == NULL) { r->bst_link[0] = p->bst_link[0]; q->bst_link[dir] = r; } else { struct bst_node *s; for (;;) { s = r->bst_link[0]; if (s->bst_link[0] == NULL) break; r = s; } r->bst_link[0] = s->bst_link[1]; s->bst_link[0] = p->bst_link[0]; s->bst_link[1] = p->bst_link[1]; q->bst_link[dir] = s; } } tree->bst_alloc->libavl_free (tree->bst_alloc, p); tree->bst_count--; tree->bst_generation++; return (void *) item; }