tpl_rb_tree.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef TPL_RB_TREE_H
00045 # define TPL_RB_TREE_H
00046 
00047 # include <ahFunction.H>
00048 # include <tpl_arrayStack.H>
00049 # include <tpl_binNodeUtils.H>
00050 # include <rbNode.H>
00051 
00052 using namespace Aleph;
00053 
00054 namespace Aleph {
00055 
00075     template <template <typename> class NodeType, typename Key, class Compare>
00076 class Gen_Rb_Tree 
00077 {
00078 
00079 public:
00080 
00081   typedef NodeType<Key> Node;
00082 
00083 
00084 private:
00085 
00086   Node                               head_node;  // Node cabecera centinela
00087   Node *                             head; // puntero a cabecera centinela
00088   Node *&                            root; // raíz
00089   FixedStack<Node*, Node::MaxHeight> rb_stack; 
00090   Node * search_and_stack_rb(const Key & key)             
00091   {
00092     Node * p = root;
00093     rb_stack.push(head);
00094       
00095     do 
00096       {
00097         rb_stack.push(p); 
00098    
00099         if (Compare () (key, KEY(p)))
00100           p = LLINK(p);
00101         else if (Compare () (KEY(p), key))
00102           p = RLINK(p);
00103         else
00104           return p;
00105       }
00106     while (p != Node::NullPtr);
00107 
00108     return rb_stack.top();
00109   }
00110   void fix_red_condition(Node * p)
00111   {
00112 
00113     I(COLOR(p) == RED);
00114 
00115     while (p != root) 
00116       {
00117         Node * pp = rb_stack.pop(); // padre de p
00118         
00119         if (COLOR(pp) == BLACK) // ¿padre de p es negro?
00120           break; // sí ==> no hay nodos rojos consecutivos ==> terminar
00121 
00122         if (root == pp) // ¿p es hijo directo de la raíz?
00123           {    // sí ==> colorear raíz de negro y terminar
00124             COLOR(root) = BLACK; 
00125             break; 
00126           }
00127 
00128         Node * ppp = rb_stack.pop(); // abuelo de p
00129         Node * spp = LLINK(ppp) == pp ? RLINK(ppp) : LLINK(ppp); // tío de p
00130 
00131         if (COLOR(spp) == RED) // ¿tío de p es rojo?
00132           {     // intercambiar colores entre los niveles
00133             COLOR(ppp) = RED;
00134             COLOR(pp)  = BLACK;
00135             COLOR(spp) = BLACK;
00136             p = ppp;
00137             continue; // avanzar al próximo ancestro y verificar violaciones
00138           }
00139 
00140         Node *pppp = rb_stack.pop(); // bisabuelo de p
00141 
00142         if (LLINK(pp) == p and LLINK(ppp) == pp)
00143           {
00144             rotate_to_right(ppp, pppp);
00145             COLOR(pp) = BLACK;
00146           }
00147         else if (RLINK(pp) == p and RLINK(ppp) == pp)
00148           {
00149             rotate_to_left(ppp, pppp);
00150             COLOR(pp) = BLACK;
00151           }
00152         else 
00153           {
00154             if (RLINK(pp) == p)
00155               {
00156                 rotate_to_left(pp, ppp);
00157                 rotate_to_right(ppp, pppp);
00158               }
00159             else
00160               {
00161                 rotate_to_right(pp, ppp);
00162                 rotate_to_left(ppp, pppp);
00163               }
00164             COLOR(p) = BLACK;
00165           }
00166         COLOR(ppp) = RED;
00167 
00168         break; // árbol es rojo-negro ==> terminar
00169       }
00170      rb_stack.empty();
00171   }
00172   void find_succ_and_swap(Node * p, Node *& pp)
00173   {
00174     Node *& ref_rb_stack = rb_stack.top(); 
00175 
00176     /* Find successor while updating rb_stack */
00177     Node * fSucc = p;        // successor's parent
00178     Node * succ  = RLINK(p); // Searching starts from p's right child 
00179 
00180     rb_stack.push(succ);
00181     while (LLINK(succ) != Node::NullPtr)  // go down to leftmost
00182       {
00183         fSucc = succ;
00184         succ  = LLINK(succ);
00185         rb_stack.push(succ);
00186       }
00187 
00188       ref_rb_stack   = succ; /* swap old top with current top */
00189       rb_stack.top() = p; 
00190 
00191       if (LLINK(pp) == p) /* Setting of parent of p to new child(succ) */ 
00192         LLINK(pp) = succ;
00193       else
00194         RLINK(pp) = succ;
00195       
00196       LLINK(succ) = LLINK(p); /* Swaps left branches */
00197       LLINK(p)    = Node::NullPtr; 
00198 
00199       if (RLINK(p) == succ) /* For right branches there are two cases */
00200         { /* successor is just right child of p */   
00201           RLINK(p)    = RLINK(succ); 
00202           RLINK(succ) = p;
00203           pp          = succ;
00204         }
00205       else
00206         { /* Successor is leftmost node descending from right child of p */ 
00207           Node *succr  = RLINK(succ); 
00208           RLINK(succ)  = RLINK(p);
00209           LLINK(fSucc) = p;
00210           RLINK(p)     = succr;
00211           pp           = fSucc;
00212         }
00213 
00214       Aleph::swap(COLOR(succ), COLOR(p));
00215     }
00216 
00217   void fix_black_condition(Node * p)
00218   {
00219     if (COLOR(p) == RED) // ¿p es rojo?
00220       {     // sí ==> lo pintamos de negro y terminamos
00221         COLOR(p) = BLACK; // esto compensa el déficit 
00222         return;
00223       }
00224 
00225     Node * pp = rb_stack.popn(2); // padre de p
00226         
00227     while (p != root)
00228       {
00229 
00230         I(LLINK(pp) == p or RLINK(pp) == p);
00231         I(LLINK(rb_stack.top()) == pp or RLINK(rb_stack.top()) == pp);
00232 
00233         Node * sp = LLINK(pp) == p ? RLINK(pp) : LLINK(pp); // hermano de p
00234         
00235         if (COLOR(sp) == RED) // ¿hermano de p es rojo?
00236           {
00237             Node *& ppp = rb_stack.top(); // abuelo de p
00238 
00239             if (LLINK(pp) == p)
00240               {
00241                 sp  = LLINK(sp);
00242                 ppp = rotate_to_left(pp, ppp);
00243               }
00244             else
00245               {
00246                 sp  = RLINK(sp);
00247                 ppp = rotate_to_right(pp, ppp);
00248               }
00249 
00250             COLOR(ppp) = BLACK;
00251             COLOR(pp)  = RED;
00252           }
00253 
00254         Node * np, * snp;
00255         if (LLINK(pp) == p) // ¿p es hijo izquierdo?
00256           {     // sí ==> que sp es hijo derechos
00257             np  = RLINK(sp);
00258             snp = LLINK(sp);
00259           }
00260         else
00261           {
00262             np  = LLINK(sp);
00263             snp = RLINK(sp);
00264           }
00265 
00266         if (COLOR(np) == RED) // ¿np es rojo?
00267           {
00268             Node * ppp = rb_stack.top();
00269 
00270             if (RLINK(sp) == np)
00271               rotate_to_left(pp, ppp);
00272              else
00273               rotate_to_right(pp, ppp);
00274 
00275             COLOR(sp) = COLOR(pp);
00276             COLOR(pp) = BLACK;
00277             COLOR(np) = BLACK;
00278             return;
00279           }
00280 
00281         if (COLOR(snp) == RED) // ¿snp es rojo?
00282           {
00283             Node * ppp = rb_stack.top();
00284 
00285             if (LLINK(sp) == snp)
00286               {
00287                 rotate_to_right(sp, pp);
00288                 rotate_to_left(pp, ppp);
00289               }
00290              else
00291                {
00292                  rotate_to_left(sp, pp);
00293                  rotate_to_right(pp, ppp);
00294                }
00295 
00296             COLOR(snp) = COLOR(pp);
00297             COLOR(pp)  = BLACK;;
00298             return;
00299           }
00300 
00301         if (color(pp) == RED) // ¿pp es rojo?
00302           {
00303             COLOR(pp) = BLACK;
00304             COLOR(sp) = RED;;
00305             return;
00306           }
00307 
00308             // no hay nodo rojo en las adyacencias de p ==> desplazar el
00309             // déficit hacia pp y repetir la iteración
00310         COLOR(sp) = RED;
00311         p         = pp;
00312         pp        = rb_stack.pop(); 
00313       }
00314   }
00315 
00316 
00317 public:
00318 
00319 
00321   Gen_Rb_Tree() : head(&head_node), root(head_node.getR()) { /* empty */ }
00322 
00324   virtual ~Gen_Rb_Tree() { /* empty */ }
00325 
00329   Node * search(const Key & key)
00330   {
00331     Node * retVal = Aleph::searchInBinTree<Node, Compare>(root, key);
00332 
00333     return retVal == Node::NullPtr ? NULL : retVal;
00334   }
00335 
00337   Node *& getRoot() { return root; }
00342   Node * insert(Node * p)
00343   {
00344 
00345     I(COLOR(p) == RED);
00346 
00347     if (root == Node::NullPtr) // inserción en árbol vacío
00348       return root = p;
00349 
00350     Node * q = search_and_stack_rb(KEY(p));
00351 
00352     if (Compare () (KEY(p), KEY(q))) 
00353       LLINK(q) = p;
00354     else if (Compare () (KEY(q), KEY(p))) 
00355       RLINK(q) = p;
00356     else
00357       {
00358         rb_stack.empty();
00359 
00360         return NULL;  // clave duplicada
00361       }
00362 
00363     fix_red_condition(p);
00364 
00365     return p;
00366   }
00371   Node* remove(const Key & key)
00372   {
00373     if (root == Node::NullPtr)
00374       return NULL;
00375         
00376     Node * q = search_and_stack_rb(key);
00377 
00378     if (no_equals<Key, Compare> (KEY(q), key))
00379       {
00380         rb_stack.empty();
00381         return NULL;
00382       }
00383 
00384     Node * pq = rb_stack.top(1); // padre de 1
00385     Node * p; // hijo de q luego de que éste ha sido eliminado
00386 
00387    repeat:   // Eliminación tradicional en árbol binario de búsqueda
00388     
00389     if (LLINK(q) == Node::NullPtr) 
00390       {
00391         if (LLINK(pq) == q)
00392           p = LLINK(pq) = RLINK(q);
00393         else
00394           p = RLINK(pq) = RLINK(q);
00395 
00396         goto end;
00397       }
00398 
00399     if (RLINK(q) == Node::NullPtr) 
00400       {
00401         if (LLINK(pq) == q)
00402           p = LLINK(pq) = LLINK(q);
00403         else
00404           p = RLINK(pq) = LLINK(q);
00405 
00406         goto end;
00407       }
00408             
00409     find_succ_and_swap(q, pq);
00410 
00411     goto repeat;
00412 
00413    end:
00414     if (COLOR(q) == BLACK) // ¿se eliminó un nodo negro?
00415       fix_black_condition(p);
00416 
00417     q->reset();
00418     rb_stack.empty();
00419         
00420     return q;
00421   }
00422 };
00423 
00438     template <typename Key, class Compare = Aleph::less<Key> >
00439 struct Rb_Tree : public Gen_Rb_Tree<RbNode, Key, Compare>
00440 { /* Empty */ };
00441 
00457     template <typename Key, class Compare = Aleph::less<Key> >
00458 struct Rb_Tree_Vtl : public Gen_Rb_Tree<RbNodeVtl, Key, Compare>
00459 { /* Empty */ };
00460 
00461 } // end namespace Aleph
00462 
00463 # endif // TPL_RB_TREE_H
00464 

Leandro R. León