fix tdelete to properly balance the tree
authorSzabolcs Nagy <nsz@port70.net>
Sat, 5 Dec 2015 20:02:34 +0000 (21:02 +0100)
committerRich Felker <dalias@aerifal.cx>
Tue, 8 Dec 2015 23:52:25 +0000 (18:52 -0500)
the tsearch data structure is an avl tree, but it did not implement
the deletion operation correctly so the tree could become unbalanced.

reported by Ed Schouten.

src/search/tsearch_avl.c

index 8620092..0864460 100644 (file)
@@ -105,10 +105,13 @@ static struct node *insert(struct node **n, const void *k,
        return r;
 }
 
-static struct node *movr(struct node *n, struct node *r) {
-       if (!n)
-               return r;
-       n->right = movr(n->right, r);
+static struct node *remove_rightmost(struct node *n, struct node **rightmost)
+{
+       if (!n->right) {
+               *rightmost = n;
+               return n->left;
+       }
+       n->right = remove_rightmost(n->right, rightmost);
        return balance(n);
 }
 
@@ -122,7 +125,13 @@ static struct node *remove(struct node **n, const void *k,
        c = cmp(k, (*n)->key);
        if (c == 0) {
                struct node *r = *n;
-               *n = movr(r->left, r->right);
+               if (r->left) {
+                       r->left = remove_rightmost(r->left, n);
+                       (*n)->left = r->left;
+                       (*n)->right = r->right;
+                       *n = balance(*n);
+               } else
+                       *n = r->right;
                free(r);
                return parent;
        }