/* Deletes from |tree| and returns an item matching |item|. Returns a null pointer if no matching item found. */ void * tbst_delete (struct tbst_table *tree, const void *item) { struct tbst_node *p; /* Node to delete. */ struct tbst_node *q; /* Parent of |p|. */ int dir; /* Index into |q->tbst_link[]| that leads to |p|. */ assert (tree != NULL && item != NULL); if (tree->tbst_root == NULL) return NULL; p = tree->tbst_root; q = (struct tbst_node *) &tree->tbst_root; dir = 0; for (;;) { int cmp = tree->tbst_compare (item, p->tbst_data, tree->tbst_param); if (cmp == 0) break; dir = cmp > 0; if (p->tbst_tag[dir] == TBST_THREAD) return NULL; q = p; p = p->tbst_link[dir]; } item = p->tbst_data; if (p->tbst_tag[1] == TBST_THREAD) { if (p->tbst_tag[0] == TBST_CHILD) { struct tbst_node *t = p->tbst_link[0]; while (t->tbst_tag[1] == TBST_CHILD) t = t->tbst_link[1]; t->tbst_link[1] = p->tbst_link[1]; q->tbst_link[dir] = p->tbst_link[0]; } else { q->tbst_link[dir] = p->tbst_link[dir]; if (q != (struct tbst_node *) &tree->tbst_root) q->tbst_tag[dir] = TBST_THREAD; } } else { struct tbst_node *r = p->tbst_link[1]; if (r->tbst_tag[0] == TBST_THREAD) { r->tbst_link[0] = p->tbst_link[0]; r->tbst_tag[0] = p->tbst_tag[0]; if (r->tbst_tag[0] == TBST_CHILD) { struct tbst_node *t = r->tbst_link[0]; while (t->tbst_tag[1] == TBST_CHILD) t = t->tbst_link[1]; t->tbst_link[1] = r; } q->tbst_link[dir] = r; } else { struct tbst_node *s; for (;;) { s = r->tbst_link[0]; if (s->tbst_tag[0] == TBST_THREAD) break; r = s; } if (s->tbst_tag[1] == TBST_CHILD) r->tbst_link[0] = s->tbst_link[1]; else { r->tbst_link[0] = s; r->tbst_tag[0] = TBST_THREAD; } s->tbst_link[0] = p->tbst_link[0]; if (p->tbst_tag[0] == TBST_CHILD) { struct tbst_node *t = p->tbst_link[0]; while (t->tbst_tag[1] == TBST_CHILD) t = t->tbst_link[1]; t->tbst_link[1] = s; s->tbst_tag[0] = TBST_CHILD; } s->tbst_link[1] = p->tbst_link[1]; s->tbst_tag[1] = TBST_CHILD; q->tbst_link[dir] = s; } } tree->tbst_alloc->libavl_free (tree->tbst_alloc, p); tree->tbst_count--; return (void *) item; }