Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

pana_rbtree.cxx

00001 /* BEGIN_COPYRIGHT                                                        */
00002 /*                                                                        */
00003 /* Open Diameter: Open-source software for the Diameter and               */
00004 /*                Diameter related protocols                              */
00005 /*                                                                        */
00006 /* Copyright (C) 2002-2004 Open Diameter Project                          */
00007 /*                                                                        */
00008 /* This library is free software; you can redistribute it and/or modify   */
00009 /* it under the terms of the GNU Lesser General Public License as         */
00010 /* published by the Free Software Foundation; either version 2.1 of the   */
00011 /* License, or (at your option) any later version.                        */
00012 /*                                                                        */
00013 /* This library is distributed in the hope that it will be useful,        */
00014 /* but WITHOUT ANY WARRANTY; without even the implied warranty of         */
00015 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      */
00016 /* Lesser General Public License for more details.                        */
00017 /*                                                                        */
00018 /* You should have received a copy of the GNU Lesser General Public       */
00019 /* License along with this library; if not, write to the Free Software    */
00020 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307    */
00021 /* USA.                                                                   */
00022 /*                                                                        */
00023 /* In addition, when you copy and redistribute some or the entire part of */
00024 /* the source code of this software with or without modification, you     */
00025 /* MUST include this copyright notice in each copy.                       */
00026 /*                                                                        */
00027 /* If you make any changes that are appeared to be useful, please send    */
00028 /* sources that include the changed part to                               */
00029 /* diameter-developers@lists.sourceforge.net so that we can reflect your  */
00030 /* changes to one unified version of this software.                       */
00031 /*                                                                        */
00032 /* END_COPYRIGHT                                                          */
00033 
00034 #include "pana_rbtree.h"
00035 
00036 RbTreeNode &RbTreeNode::operator=(RbTreeNode &source)
00037 {
00038    left = source.left;
00039    right = source.right;
00040    parent = source.parent;
00041    color = source.color;
00042    data = source.data;
00043    return (*this);
00044 }
00045 
00046 RbTreeNode::RbTreeNode()
00047 {
00048    left = right = this;
00049    parent = (0);
00050    color = RBTREE_CLR_BLACK;
00051    data = (0);
00052 }
00053 
00054 void RbTreeTree::RotateLeft(RbTreeNode *x)
00055 {
00056     RbTreeNode *y = x->right;
00057 
00058     // establish x->right link 
00059     x->right = y->left;
00060     if (y->left != &nil) {
00061         y->left->parent = x;
00062     }
00063 
00064     // establish y->parent link 
00065     if (y != &nil) {
00066         y->parent = x->parent;
00067     }
00068     if (x->parent) {
00069         if (x == x->parent->left)
00070             x->parent->left = y;
00071         else
00072             x->parent->right = y;
00073     } else {
00074         root = y;
00075     }
00076 
00077     // link x and y 
00078     y->left = x;
00079     if (x != &nil) {
00080         x->parent = y;
00081     }
00082 }
00083 
00084 void RbTreeTree::RotateRight(RbTreeNode *x)
00085 {
00086     RbTreeNode *y = x->left;
00087 
00088     // establish x->left link
00089     x->left = y->right;
00090     if (y->right != &nil) {
00091         y->right->parent = x;
00092     }
00093 
00094     // establish y->parent link 
00095     if (y != &nil) {
00096         y->parent = x->parent;
00097     }
00098     if (x->parent) {
00099         if (x == x->parent->right)
00100             x->parent->right = y;
00101         else
00102             x->parent->left = y;
00103     } else {
00104         root = y;
00105     }
00106 
00107     // link x and y 
00108     y->right = x;
00109     if (x != &nil) {
00110         x->parent = y;
00111     }
00112 }
00113 
00114 void RbTreeTree::FixupRemove(RbTreeNode *x)
00115 {
00116     while (x != root && x->color == RBTREE_CLR_BLACK) {
00117         if (x == x->parent->left) {
00118             RbTreeNode *w = x->parent->right;
00119             if (w->color == RBTREE_CLR_RED) {
00120                 w->color = RBTREE_CLR_BLACK;
00121                 x->parent->color = RBTREE_CLR_RED;
00122                 RotateLeft (x->parent);
00123                 w = x->parent->right;
00124             }
00125             if (w->left->color == RBTREE_CLR_BLACK && w->right->color == RBTREE_CLR_BLACK) {
00126                 w->color = RBTREE_CLR_RED;
00127                 x = x->parent;
00128             } else {
00129                 if (w->right->color == RBTREE_CLR_BLACK) {
00130                     w->left->color = RBTREE_CLR_BLACK;
00131                     w->color = RBTREE_CLR_RED;
00132                     RotateRight (w);
00133                     w = x->parent->right;
00134                 }
00135                 w->color = x->parent->color;
00136                 x->parent->color = RBTREE_CLR_BLACK;
00137                 w->right->color = RBTREE_CLR_BLACK;
00138                 RotateLeft (x->parent);
00139                 x = root;
00140             }
00141         } else {
00142             RbTreeNode *w = x->parent->left;
00143             if (w->color == RBTREE_CLR_RED) {
00144                 w->color = RBTREE_CLR_BLACK;
00145                 x->parent->color = RBTREE_CLR_RED;
00146                 RotateRight (x->parent);
00147                 w = x->parent->left;
00148             }
00149             if (w->right->color == RBTREE_CLR_BLACK && w->left->color == RBTREE_CLR_BLACK) {
00150                 w->color = RBTREE_CLR_RED;
00151                 x = x->parent;
00152             } else {
00153                 if (w->left->color == RBTREE_CLR_BLACK) {
00154                     w->right->color = RBTREE_CLR_BLACK;
00155                     w->color = RBTREE_CLR_RED;
00156                     RotateLeft (w);
00157                     w = x->parent->left;
00158                 }
00159                 w->color = x->parent->color;
00160                 x->parent->color = RBTREE_CLR_BLACK;
00161                 w->left->color = RBTREE_CLR_BLACK;
00162                 RotateRight (x->parent);
00163                 x = root;
00164             }
00165         }
00166     }
00167     x->color = RBTREE_CLR_BLACK;
00168 }
00169 
00170 void RbTreeTree::FixupInsert(RbTreeNode *x)
00171 {
00172     // check Red-Black properties
00173     while (x != root && x->parent->color == RBTREE_CLR_RED) {
00174         // violation
00175         if (x->parent == x->parent->parent->left) {
00176             RbTreeNode *y = x->parent->parent->right;
00177             if (y->color == RBTREE_CLR_RED) {
00178 
00179                 // uncle is RBTREE_CLR_RED
00180                 x->parent->color = RBTREE_CLR_BLACK;
00181                 y->color = RBTREE_CLR_BLACK;
00182                 x->parent->parent->color = RBTREE_CLR_RED;
00183                 x = x->parent->parent;
00184             } else {
00185 
00186                 // uncle is RBTREE_CLR_BLACK
00187                 if (x == x->parent->right) {
00188                     // make x a left child
00189                     x = x->parent;
00190                     RotateLeft(x);
00191                 }
00192 
00193                 // recolor and rotate 
00194                 x->parent->color = RBTREE_CLR_BLACK;
00195                 x->parent->parent->color = RBTREE_CLR_RED;
00196                 RotateRight(x->parent->parent);
00197             }
00198         } else {
00199 
00200             // mirror image of above code 
00201             RbTreeNode *y = x->parent->parent->left;
00202             if (y->color == RBTREE_CLR_RED) {
00203 
00204                 // uncle is RBTREE_CLR_RED
00205                 x->parent->color = RBTREE_CLR_BLACK;
00206                 y->color = RBTREE_CLR_BLACK;
00207                 x->parent->parent->color = RBTREE_CLR_RED;
00208                 x = x->parent->parent;
00209             } else {
00210 
00211                 // uncle is RBTREE_CLR_BLACK 
00212                 if (x == x->parent->left) {
00213                     x = x->parent;
00214                     RotateRight(x);
00215                 }
00216                 x->parent->color = RBTREE_CLR_BLACK;
00217                 x->parent->parent->color = RBTREE_CLR_RED;
00218                 RotateLeft(x->parent->parent);
00219             }
00220         }
00221     }
00222     root->color = RBTREE_CLR_BLACK;
00223 }
00224 
00225 RbTreeData *RbTreeTree::Insert(RbTreeData *data)
00226 {
00227     RbTreeNode *parent = (0), *current = root;
00228 
00229     while (current != &nil) {
00230        if (*(current->data) == (*data)) {
00231            return (current->data);
00232        }
00233        parent = current;
00234        current = ((*data) < (*(current->data))) ?
00235            current->left : current->right;
00236     }
00237 
00238     current = new RbTreeNode;
00239     if (! current) {
00240         return (0);
00241     }
00242 
00243     current->left = current->right = &nil;
00244     current->parent = parent;
00245     current->color = RBTREE_CLR_RED;
00246     current->data = data;
00247 
00248     if (parent) {
00249         if ((*data) < (*(parent->data))) {
00250             parent->left = current;
00251         }
00252         else {
00253            parent->right = current;
00254         }
00255     }
00256     else {      
00257         root = current;
00258     }
00259 
00260     FixupInsert(current);
00261     return (current->data);
00262 }
00263 
00264 RbTreeData *RbTreeTree::Find(RbTreeData *data)
00265 {
00266     RbTreeNode *current = root;
00267     
00268     while (current != &nil) {
00269        if (*(current->data) == (*data)) {
00270            return (current->data);
00271        }
00272        current = ((*data) < (*(current->data))) ?
00273            current->left : current->right;
00274     }
00275 
00276     return (0);
00277 }
00278 
00279 RbTreeData *RbTreeTree::Remove(RbTreeData *data)
00280 {
00281     RbTreeData *val;
00282     RbTreeNode *x, *y, *z = root;
00283 
00284     while (z != &nil) {
00285        if (*(z->data) == (*data)) {
00286            break;
00287        }
00288        z = ((*data) < (*(z->data))) ? z->left : z->right;
00289     }
00290     
00291     if (!z || z == &nil) {
00292         return (0);
00293     }
00294 
00295     if (z->left == &nil || z->right == &nil) {
00296         // y has a nil node as a child 
00297         y = z;
00298     } else {
00299         // find tree successor with a nil node as a child 
00300         y = z->right;
00301         while (y->left != &nil) {
00302            y = y->left;
00303         }
00304     }
00305 
00306     // x is y's only child
00307     if (y->left != &nil) {
00308         x = y->left;
00309     } else {
00310         x = y->right;
00311     }
00312 
00313     // remove y from the parent chain
00314     x->parent = y->parent;
00315     if (y->parent) {
00316         if (y == y->parent->left) {
00317             y->parent->left = x;
00318         } else {
00319             y->parent->right = x;
00320         }
00321     } else {
00322         root = x;
00323     }
00324 
00325     if (y != z) {
00326         val = z->data;
00327         z->data = y->data;
00328     }
00329     else {
00330         val = y->data;
00331     }
00332 
00333     if (y->color == RBTREE_CLR_BLACK) {
00334         FixupRemove(x);
00335     }
00336 
00337     delete y;
00338     return (val);
00339 }
00340 
00341 void RbTreeTree::Clear(void *userData)
00342 {
00343     RbTreeData *val;
00344     while (root != &nil) {
00345        val = RbTreeTree::Remove(root->data);
00346        val->clear(userData);
00347        delete val;
00348     }
00349 }
00350 
00351 void RbTreeTree::Dump(RbTreeNode *x, void *userData)
00352 {
00353     if (x == 0) {
00354         x = root;
00355     }
00356     if (x == &nil) {
00357         return;
00358     }
00359     if (x->left != &nil) {
00360         Dump(x->left, userData);
00361     }
00362     if (x->data) {
00363         x->data->Dump(userData);
00364     } else {
00365     }
00366     if (x->right != &nil) {
00367         Dump(x->right, userData);
00368     }
00369 }

Generated on Fri Jun 25 19:18:30 2004 for PANA by doxygen 1.3.5