]> granicus.if.org Git - sudo/commitdiff
Replace my rbdelete with Emin's version (which actually works ;-)
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sat, 22 Nov 2008 14:42:42 +0000 (14:42 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sat, 22 Nov 2008 14:42:42 +0000 (14:42 +0000)
redblack.c

index b001867d3b36facc45b050f8d13df6e9d65caba1..526c603e56a9ae0ada6ea84662a2374433f690fb 100644 (file)
@@ -18,6 +18,8 @@
  * Adapted from the following code written by Emin Martinian:
  * http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
  *
+ * Copyright (c) 2001 Emin Martinian
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that neither the name of Emin
  * Martinian nor the names of any contributors are be used to endorse or
@@ -367,59 +369,45 @@ rbdestroy(tree, destroy)
 }
 
 /*
- * Delete victim from tree and return its data pointer.
+ * Delete node 'z' from the tree and return its data pointer.
  */
-void *
-rbdelete(tree, victim)
-    struct rbtree *tree;
-    struct rbnode *victim;
+void *rbdelete(tree, z)
+    struct rbtree* tree;
+    struct rbnode* z;
 {
-    struct rbnode *pred, *succ;
-    void *data;
+    struct rbnode *x, *y;
+    void *data = z->data;
 
-    if (victim->left != rbnil(tree) && victim->right != rbnil(tree)) {
-       succ = rbsuccessor(tree, victim);
-       pred = succ->left == rbnil(tree) ? succ->right : succ->left;
-       if (succ->parent == rbroot(tree)) {
-           pred->parent = rbroot(tree);
-           rbfirst(tree) = pred;
-       } else {
-           if (succ == succ->parent->left)
-               succ->parent->left = pred;
-           else
-               succ->parent->right = pred;
-       }
-       if ((succ->color == black))
-           rbrepair(tree, pred);
-
-       succ->left = victim->left;
-       succ->right = victim->right;
-       succ->parent = victim->parent;
-       succ->color = victim->color;
-       victim->left->parent = victim->right->parent = succ;
-       if (victim == victim->parent->left)
-           victim->parent->left = succ;
-       else
-           victim->parent->right = succ;
-       data = victim->data;
-       efree(victim);
+    if (z->left == rbnil(tree) || z->right == rbnil(tree))
+       y = z;
+    else
+       y = rbsuccessor(tree, z);
+    x = (y->left == rbnil(tree)) ? y->right : y->left;
+
+    if ((x->parent = y->parent) == rbroot(tree)) {
+       rbfirst(tree) = x;
     } else {
-       pred = victim->left == rbnil(tree) ? victim->right : victim->left;
-       if (victim->parent == rbroot(tree)) {
-           pred->parent = rbroot(tree);
-           rbfirst(tree) = pred;
-       } else {
-           if (victim == victim->parent->left)
-               victim->parent->left = pred;
-           else
-               victim->parent->right = pred;
-       }
-       if (victim->color == black)
-           rbrepair(tree, pred);
-       data = victim->data;
-       efree(victim);
+       if (y == y->parent->left)
+           y->parent->left = x;
+       else
+           y->parent->right = x;
+    }
+    if (y->color == black)
+       rbrepair(tree, x);
+    if (y != z) {
+       y->left = z->left;
+       y->right = z->right;
+       y->parent = z->parent;
+       y->color = z->color;
+       z->left->parent = z->right->parent = y;
+       if (z == z->parent->left)
+           z->parent->left = y; 
+       else
+           z->parent->right = y;
     }
-    return(data);
+    free(z); 
+    
+    return (data);
 }
 
 /*
@@ -431,9 +419,10 @@ rbrepair(tree, node)
     struct rbtree *tree;
     struct rbnode *node;
 {
+    struct rbnode *first = rbfirst(tree);
     struct rbnode *sibling;
 
-    while (node->color == black && node != rbfirst(tree)) {
+    while (node->color == black) {
        if (node == node->parent->left) {
            sibling = node->parent->right;
            if (sibling->color == red) {
@@ -456,7 +445,7 @@ rbrepair(tree, node)
                node->parent->color = black;
                sibling->right->color = black;
                rotate_left(tree, node->parent);
-               return; /* XXX */
+               break;
            }
        } else { /* if (node == node->parent->right) */
            sibling = node->parent->left;
@@ -480,9 +469,8 @@ rbrepair(tree, node)
                node->parent->color = black;
                sibling->left->color = black;
                rotate_right(tree, node->parent);
-               return; /* XXX */
+               break;
            }
        }
     }
-    node->color = black;
 }