rb_delete.c

Go to the documentation of this file.
00001 /*                     R B _ D E L E T E . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1998-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 /** \addtogroup rb  */
00022 /*@{*/
00023 /** @file rb_delete.c
00024  *          Routines to delete a node from a red-black tree
00025  *
00026  *
00027  *  @author     Paul J. Tanenbaum
00028  *
00029  * @par  Source -
00030  *      The U. S. Army Research Laboratory
00031  *@n    Aberdeen Proving Ground, Maryland  21005-5068  USA
00032  */
00033 /*@}*/
00034 
00035 #ifndef lint
00036 static char const libbu_rb_delete_RCSid[] = "@(#) $Header: /cvsroot/brlcad/brlcad/src/libbu/rb_delete.c,v 14.14 2006/08/31 23:16:38 lbutler Exp $";
00037 #endif
00038 
00039 #include "common.h"
00040 
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <math.h>
00044 
00045 #include "machine.h"
00046 #include "bu.h"
00047 #include "./rb_internals.h"
00048 
00049 
00050 /**                     B U _ R B _ F I X U P ( )
00051  *
00052  *          Restore the red-black properties of a red-black tree
00053  *                  after the splicing out of a node
00054  *
00055  *      This function has three parameters: the tree to be fixed up,
00056  *      the node where the trouble occurs, and the order.  bu_rb_fixup()
00057  *      is an implementation of the routine RB-DELETE-FIXUP on p. 274
00058  *      of Cormen et al.
00059  */
00060 static void bu_rb_fixup (bu_rb_tree *tree, struct bu_rb_node *node, int order)
00061 {
00062     int                 direction;
00063     struct bu_rb_node   *parent;
00064     struct bu_rb_node   *w;
00065 
00066     BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
00067     BU_CKMAG(node, BU_RB_NODE_MAGIC, "red-black node");
00068     BU_RB_CKORDER(tree, order);
00069 
00070     while ((node != bu_rb_root(tree, order))
00071         && (bu_rb_get_color(node, order) == BU_RB_BLACK))
00072     {
00073         parent = bu_rb_parent(node, order);
00074         if (node == bu_rb_left_child(parent, order))
00075             direction = BU_RB_LEFT;
00076         else
00077             direction = BU_RB_RIGHT;
00078 
00079         w = bu_rb_other_child(parent, order, direction);
00080         if (bu_rb_get_color(w, order) == BU_RB_RED)
00081         {
00082             bu_rb_set_color(w, order, BU_RB_BLACK);
00083             bu_rb_set_color(parent, order, BU_RB_RED);
00084             bu_rb_rotate(parent, order, direction);
00085             w = bu_rb_other_child(parent, order, direction);
00086         }
00087         if ((bu_rb_get_color(bu_rb_child(w, order, direction), order)
00088                 == BU_RB_BLACK)
00089          && (bu_rb_get_color(bu_rb_other_child(w, order, direction), order)
00090                  == BU_RB_BLACK))
00091         {
00092             bu_rb_set_color(w, order, BU_RB_RED);
00093             node = parent;
00094         }
00095         else
00096         {
00097             if (bu_rb_get_color(bu_rb_other_child(w, order, direction),
00098                 order)
00099                     == BU_RB_BLACK)
00100             {
00101                 bu_rb_set_color(bu_rb_child(w, order, direction), order,
00102                     BU_RB_BLACK);
00103                 bu_rb_set_color(w, order, BU_RB_RED);
00104                 bu_rb_other_rotate(w, order, direction);
00105                 w = bu_rb_other_child(parent, order, direction);
00106             }
00107             bu_rb_set_color(w, order, bu_rb_get_color(parent, order));
00108             bu_rb_set_color(parent, order, BU_RB_BLACK);
00109             bu_rb_set_color(bu_rb_other_child(w, order, direction),
00110                                 order, BU_RB_BLACK);
00111             bu_rb_rotate(parent, order, direction);
00112             node = bu_rb_root(tree, order);
00113         }
00114     }
00115     bu_rb_set_color(node, order, BU_RB_BLACK);
00116 }
00117 
00118 /**                     _ R B _ D E L E T E ( )
00119  *
00120  *              Delete a node from one order of a red-black tree
00121  *
00122  *      This function has three parameters: a tree, the node to delete,
00123  *      and the order from which to delete it.  _rb_delete() is an
00124  *      implementation of the routine RB-DELETE on p. 273 of Cormen et al.
00125  */
00126 static void _rb_delete (bu_rb_tree *tree, struct bu_rb_node *node, int order)
00127 {
00128     struct bu_rb_node   *y;             /* The node to splice out */
00129     struct bu_rb_node   *parent;
00130     struct bu_rb_node   *only_child;
00131 
00132     BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
00133     BU_CKMAG(node, BU_RB_NODE_MAGIC, "red-black node");
00134     BU_RB_CKORDER(tree, order);
00135 
00136     if (tree -> rbt_debug & BU_RB_DEBUG_DELETE)
00137         bu_log("_rb_delete(%x,%x,%d): data=x%x\n",
00138             tree, node, order, bu_rb_data(node, order));
00139 
00140     if ((bu_rb_left_child(node, order) == bu_rb_null(tree))
00141      || (bu_rb_right_child(node, order) == bu_rb_null(tree)))
00142         y = node;
00143     else
00144         y = _rb_neighbor(node, order, SENSE_MAX);
00145 
00146     if (bu_rb_left_child(y, order) == bu_rb_null(tree))
00147         only_child = bu_rb_right_child(y, order);
00148     else
00149         only_child = bu_rb_left_child(y, order);
00150 
00151     parent = bu_rb_parent(only_child, order) = bu_rb_parent(y, order);
00152     if (parent == bu_rb_null(tree))
00153         bu_rb_root(tree, order) = only_child;
00154     else if (y == bu_rb_left_child(parent, order))
00155         bu_rb_left_child(parent, order) = only_child;
00156     else
00157         bu_rb_right_child(parent, order) = only_child;
00158 
00159     /*
00160      *  Splice y out if it's not node
00161      */
00162     if (y != node)
00163     {
00164         (node -> rbn_package)[order] = (y -> rbn_package)[order];
00165         ((node -> rbn_package)[order] -> rbp_node)[order] = node;
00166     }
00167 
00168     if (bu_rb_get_color(y, order) == BU_RB_BLACK)
00169         bu_rb_fixup(tree, only_child, order);
00170 
00171     if (--(y -> rbn_pkg_refs) == 0)
00172         bu_rb_free_node(y);
00173 }
00174 
00175 /**                     B U _ R B _ D E L E T E ( )
00176  *
00177  *              Applications interface to _rb_delete()
00178  *
00179  *      This function has two parameters: the tree and order from which
00180  *      to do the deleting.  bu_rb_delete() removes the data block stored
00181  *      in the current node (in the position of the specified order)
00182  *      from every order in the tree.
00183  */
00184 void bu_rb_delete (bu_rb_tree *tree, int order)
00185 {
00186     int                         nm_orders;
00187     struct bu_rb_node           **node;         /* Nodes containing data */
00188     struct bu_rb_package        *package;
00189 
00190     BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
00191     BU_RB_CKORDER(tree, order);
00192 
00193     if (tree -> rbt_nm_nodes <= 0)
00194     {
00195         bu_log("Error: Attempt to delete from tree with %d nodes\n",
00196                 tree -> rbt_nm_nodes);
00197         bu_bomb("");
00198     }
00199     if (bu_rb_current(tree) == bu_rb_null(tree))
00200     {
00201         bu_log("Warning: bu_rb_delete(): current node is undefined\n");
00202         return;
00203     }
00204 
00205     nm_orders = tree -> rbt_nm_orders;
00206     package = (bu_rb_current(tree) -> rbn_package)[order];
00207 
00208     node = (struct bu_rb_node **)
00209             bu_malloc(nm_orders * sizeof(struct bu_rb_node *), "node list");
00210 
00211     for (order = 0; order < nm_orders; ++order)
00212         node[order] = (package -> rbp_node)[order];
00213 
00214     /*
00215      *  Do the deletion from each order
00216      */
00217     for (order = 0; order < nm_orders; ++order)
00218         _rb_delete(tree, node[order], order);
00219 
00220     --(tree -> rbt_nm_nodes);
00221     bu_rb_free_package(package);
00222     bu_free((genptr_t) node, "node list");
00223 }
00224 /*@}*/
00225 /*
00226  * Local Variables:
00227  * mode: C
00228  * tab-width: 8
00229  * c-basic-offset: 4
00230  * indent-tabs-mode: t
00231  * End:
00232  * ex: shiftwidth=4 tabstop=8
00233  */

Generated on Mon Sep 18 01:24:48 2006 for BRL-CAD by  doxygen 1.4.6