tpl_avl.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_AVL_H
00045 # define TPL_AVL_H
00046 
00047 # include <ahFunction.H>
00048 # include <tpl_arrayStack.H>
00049 # include <avlNode.H>
00050 # include <tpl_binNodeUtils.H>
00051 
00052 using namespace Aleph;
00053 
00054 namespace Aleph {
00055 
00075     template <template <typename> class NodeType, typename Key, class Compare>
00076 class Gen_Avl_Tree
00077 {
00078 
00079 public:
00080 
00081   typedef NodeType<Key> Node;
00082 
00083 private:
00084 
00085   FixedStack<Node *, Node::MaxHeight> avl_stack;
00086   Node    head_node; 
00087   Node *  head_ptr;  
00088   Node *& root;      
00089   Compare cmp;       
00090   bool avl_stack_empty() { return avl_stack.top() == head_ptr; }
00091 
00092   void clean_avl_stack() { avl_stack.popn (avl_stack.size() - 1); }
00093   Node * search_and_stack_avl(const Key &  key)
00094   {
00095 
00096     I(avl_stack_empty());
00097 
00098     Node * p = root;
00099 
00100     do // desciende en búsqueda de key y empila el camino de búsqueda
00101       {
00102         avl_stack.push(p);
00103 
00104         if (cmp(key, KEY(p))) // ¿key < KEY(p)?
00105           p = LLINK(p);
00106         else if (cmp(KEY(p), key)) // ¿key > KEY(p)?
00107           p = RLINK(p);
00108         else
00109           return p; // clave duplicada
00110       }
00111     while (p != Node::NullPtr);
00112 
00113     return avl_stack.top();
00114   }
00115   static Node * rotateLeft(Node * p)
00116   {
00117     I(DIFF(p) == 2);
00118     I(RLINK(p) != Node::NullPtr);
00119 
00120     Node * q = RLINK(p); 
00121     RLINK(p) = LLINK(q);
00122     LLINK(q) = p;
00123 
00124     if (DIFF(q) == 0)      // ajuste de los factores de equilibrio
00125       { // este caso ocurre durante la eliminación
00126         DIFF(q) = -1;
00127         DIFF(p) = 1;
00128       }
00129     else
00130       DIFF(q) = DIFF(p) = 0;
00131 
00132     return q;
00133   }
00134 
00135   static Node * rotateRight(Node * p)
00136   {
00137     I(DIFF(p) == -2);
00138     I(LLINK(p) != Node::NullPtr);
00139 
00140     Node * q = LLINK(p); 
00141     LLINK(p) = RLINK(q);
00142     RLINK(q) = p;
00143 
00144     if (DIFF(q) == 0)       // ajuste de los factores de equilibrio
00145       { // este caso ocurre durante la eliminación
00146         DIFF(q) = 1;
00147         DIFF(p) = -1;
00148       }
00149     else
00150       DIFF(q) = DIFF(p) = 0;
00151 
00152     return q;
00153   }
00154   static Node * doubleRotateLeft(Node * p)
00155   {
00156     I(DIFF(p) == 2 or DIFF(p) == -2);
00157     I(RLINK(p) != Node::NullPtr and LLINK(RLINK(p)) != Node::NullPtr);
00158 
00159     Node * q = RLINK(p);
00160     Node * r = LLINK(q);
00161     RLINK(p) = LLINK(r);
00162     LLINK(q) = RLINK(r);
00163     LLINK(r) = p;
00164     RLINK(r) = q;
00165 
00166     unsigned char b; // altura lógica de hijo izq de r
00167     unsigned char c; // altura lógica de hijo der de r
00168 
00169         // Determinación de alturas lógicas de p, q y r 
00170     if (DIFF(r) == 1) // ==> c > b ==> c-b == 1
00171       {
00172         c = 1;
00173         b = 0;
00174       }
00175     else if (DIFF(r) == -1) // ==> c < b ==> c-b = -1
00176       {
00177         c = 0;
00178         b = 1;
00179       }
00180     else
00181       c = b = 1;
00182             
00183         // ajuste de factores de equilibrio
00184     DIFF(r) = 0; 
00185     DIFF(p) = b - 1; // altura lógica de hijo izq de p es 1
00186     DIFF(q) = 1 - c; // altura lógica de hijo der de q es 1
00187 
00188     return r;
00189   }
00190 
00191   static Node * doubleRotateRight(Node * p)
00192   {
00193     I(DIFF(p) == 2 or DIFF(p) == -2);
00194     I(LLINK(p) != Node::NullPtr and 
00195        RLINK(LLINK(p)) != Node::NullPtr);
00196 
00197     Node * q  = LLINK(p);
00198     Node * r  = RLINK(q);
00199     LLINK(p) = RLINK(r);
00200     RLINK(q) = LLINK(r);
00201     RLINK(r) = p;
00202     LLINK(r) = q;
00203 
00204     unsigned char b; // altura lógica de hijo izq de r
00205     unsigned char c; // altura lógica de hijo der de r
00206 
00207         // determinación de alturas lógicas de hijos de p, q y r
00208     if (DIFF(r) == 1) // ==> c > b ==> c-b == 1
00209       {
00210         c = 1;
00211         b = 0;
00212       }
00213     else if (DIFF(r) == -1) // ==> c < b ==> c-b == -1
00214       {
00215         c = 0;
00216         b = 1;
00217       }
00218     else
00219       c = b = 1;
00220 
00221         // ajuste de factores de equilibrio
00222     DIFF(r) = 0;
00223     DIFF(p) = 1 - c; // altura lógica de hijo der de p es 1
00224     DIFF(q) = b - 1; // altura lógica de hijo izq de p es 1
00225 
00226     return r;
00227   }
00228   enum Rotation_Type 
00229   { ROTATE_LEFT, ROTATE_RIGHT, DOUBLE_ROTATE_LEFT, DOUBLE_ROTATE_RIGHT };
00230   static Rotation_Type rotation_type(Node * p) 
00231   {
00232 
00233     I(DIFF(p) == 2 or DIFF(p) == -2);
00234 
00235     Node * pc; // p's child
00236 
00237     if (DIFF(p) == 2) // hacia la izquierda
00238       {
00239         pc = RLINK(p);
00240         if (DIFF(pc) == 1 or DIFF(pc) == 0) 
00241           return ROTATE_LEFT;
00242 
00243         return DOUBLE_ROTATE_LEFT;
00244       }
00245 
00246     pc = LLINK(p);
00247     if (DIFF(pc) == -1 or DIFF(pc) == 0) 
00248       return ROTATE_RIGHT;
00249 
00250     return DOUBLE_ROTATE_RIGHT;
00251   }
00252   static Node * restore_avl(Node * p, Node * pp)
00253   {
00254 
00255     I(LLINK(pp) == p or RLINK(pp) == p);
00256     I(DIFF(p) == -2 or DIFF(p) == 2);
00257 
00258     Node ** link = LLINK(pp) == p ? &LLINK(pp) : &RLINK(pp);
00259         
00260     switch (rotation_type(p))
00261       {
00262       case ROTATE_LEFT:         return *link = rotateLeft(p);
00263       case ROTATE_RIGHT:        return *link = rotateRight(p);
00264       case DOUBLE_ROTATE_LEFT:  return *link = doubleRotateLeft(p);
00265       case DOUBLE_ROTATE_RIGHT: return *link = doubleRotateRight(p); 
00266 
00267       default:
00268         ERROR("Invalid rotation type");
00269         break;
00270 
00271       }
00272     return NULL;
00273   }
00274   void restore_avl_after_insertion(const Key & key) 
00275   {
00276     Node *pp  = avl_stack.pop(); // padre del nodo insertado
00277 
00278     if (key > KEY(pp)) // ajuste el factor del padre del nodo insertado
00279       DIFF(pp)++;
00280     else
00281       DIFF(pp)--;
00282 
00283     if (DIFF(pp) == 0) 
00284       {    // en este caso, altura del ascendiente de pp no aumenta
00285         clean_avl_stack();                      
00286         return;
00287       }
00288 
00289     if (avl_stack_empty()) 
00290       return; // pp es raíz
00291 
00292     Node *gpp; // padre de pp
00293 
00294     do     // buscar nodo con factor igual a 0
00295       {
00296         gpp = avl_stack.pop(); 
00297 
00298             // actualizar factores de equilibrio
00299         if (key > KEY(gpp)) 
00300           DIFF(gpp)++;
00301         else
00302           DIFF(gpp)--;
00303 
00304         if (DIFF(gpp) == 0)
00305           break; // no se necesita reajuste
00306         else if (DIFF(gpp) == -2 or DIFF(gpp) == 2) // ¿se viola condición AVL?
00307           {      // se requiere reajuste
00308             Node *ggpp = avl_stack.pop();
00309             restore_avl(gpp, ggpp);
00310             break;
00311           }
00312       }
00313     while (not avl_stack_empty());
00314 
00315     clean_avl_stack();
00316   }
00317   Node* swapWithSuccessor(Node * p, Node *& pp)
00318   {
00319         // Referencia al tope de la pila, pues p será intercambiado con el
00320         // sucesor y la posición en la pila la ocupará el sucesor de p
00321     Node *& ref_to_stack_top = avl_stack.top();
00322 
00323         // encuentre el sucesor a la vez que actualiza la pila
00324     Node *fSucc = p;        // padre del sucesor
00325     Node *succ  = RLINK(p); // búsqueda comienza desde RLINK(p)
00326     avl_stack.push(succ);
00327     while (LLINK(succ) != Node::NullPtr) // descienda hasta el más a la izquierda
00328       {
00329         fSucc = succ;
00330         succ  = LLINK(succ);
00331         avl_stack.push(succ);
00332       }
00333         
00334         // actualice antigua entrada de pila ocupada por p. Estas operaciones 
00335         // son equivalentes a intercambiar el antiguo tope (antes de buscar 
00336         // sucesor) con el actual 
00337     ref_to_stack_top = succ; 
00338     avl_stack.top()  = p;    
00339 
00340         // actualice el nuevo hijo de pp (el sucesor)
00341     if (LLINK(pp) == p)
00342       LLINK(pp) = succ;
00343     else
00344       RLINK(pp) = succ;
00345       
00346         // intercambie las ramas izquierdas
00347     LLINK(succ) = LLINK(p);
00348     LLINK(p)    = Node::NullPtr; 
00349 
00350         // actualice ramas derechas
00351     if (RLINK(p) == succ) 
00352       {     // sucesor es exactamente el hijo derecho de p
00353         RLINK(p)    = RLINK(succ); 
00354         RLINK(succ) = p;
00355         pp          = succ;
00356       }
00357     else
00358       {     // sucesor es el descendiente más a la izquierda de RLINK(p)
00359         Node *succr  = RLINK(succ); 
00360         RLINK(succ)  = RLINK(p);
00361         LLINK(fSucc) = p;
00362         RLINK(p)     = succr;
00363         pp           = fSucc;
00364       }
00365     DIFF(succ) = DIFF(p); // intercambie factores de equilibrio
00366 
00367     return succ;
00368   }
00369   void restore_avl_after_deletion(const Key & key)
00370   {
00371     Node* pp = avl_stack.top(1); // padre de p
00372 
00373     Node* ppp = avl_stack.popn(3); // elimina de pila p, su padre y su abuelo
00374 
00375     while (true)
00376       {    // actualice factores de equilibrio
00377         if (key >= KEY(pp)) 
00378           DIFF(pp)--;
00379         else
00380           DIFF(pp)++;
00381             
00382         if (DIFF(pp) == -2 or DIFF(pp) == 2) // verifique una violación AVL
00383           pp = restore_avl(pp, ppp);
00384 
00385         if (DIFF(pp) != 0 or pp == root)
00386           break; // altura global del árbol no ha cambiado ==> terminar
00387 
00388         pp  = ppp; // avance al próximo ascendiente
00389         ppp = avl_stack.pop();
00390       }
00391 
00392       clean_avl_stack();
00393     }
00394 
00395 public:
00396 
00398   Gen_Avl_Tree() : head_ptr(&head_node), root(RLINK (head_ptr))
00399   {
00400     avl_stack.push(head_ptr);
00401   }
00402 
00404   virtual ~Gen_Avl_Tree() { I(avl_stack_empty()); }
00405 
00407   Node *& getRoot() { return root; }
00408 
00411   Node * search(const Key& key) const 
00412   { 
00413     return searchInBinTree<Node, Compare>(root, key); 
00414   }
00418   Node * insert(Node * p)
00419   {
00420     if (root == Node::NullPtr)
00421       {
00422         root = p;
00423         return p;
00424       }
00425    
00426     Node *pp = search_and_stack_avl(KEY(p));
00427 
00428     if (cmp (KEY(p), KEY(pp))) 
00429       LLINK (pp) = p;
00430     else if (cmp (KEY(pp), KEY(p)))
00431       RLINK(pp) = p;
00432     else
00433       { // clave duplicada
00434         clean_avl_stack();
00435 
00436         return NULL;  
00437       }
00438 
00439     restore_avl_after_insertion(KEY(p));
00440 
00441     return p;
00442   }
00446   Node * remove(const Key & key)
00447   {
00448     if (root == Node::NullPtr)
00449       return NULL;
00450         
00451     Node * p = search_and_stack_avl(key);
00452 
00453     if (no_equals<Key, Compare> (KEY(p), key))
00454       {     // clave no fue encontrada
00455         clean_avl_stack();
00456 
00457         return NULL;
00458       }
00459 
00460     Key removed_key = KEY(p);
00461     Node * pp = avl_stack.top(1); // obtener padre de p
00462        
00463     while (true) 
00464       {
00465         if (LLINK(p) == Node::NullPtr) // ¿Está incompleto por la izquierda?
00466           {      // Sí, ate a pp el hijo de p 
00467             if (LLINK(pp) == p)
00468               LLINK(pp) = RLINK(p);
00469             else
00470               RLINK(pp) = RLINK(p);
00471 
00472             break;
00473           }
00474 
00475         if (RLINK(p) == Node::NullPtr) // ¿Está incompleto por la izquierda?
00476           {     // Sí, ate a pp el hijo de p 
00477             if (LLINK(pp) == p)
00478               LLINK(pp) = LLINK(p);
00479             else
00480               RLINK(pp) = LLINK(p);
00481 
00482             break;
00483           }
00484 
00485             // en este punto, p es un nodo completo ==> intercambiar por sucesor 
00486         Node * succ = swapWithSuccessor(p, pp);
00487         removed_key = KEY(succ);
00488       }
00489 
00490      p->reset();
00491 
00492 
00493      if (pp == head_ptr) // verifique si se eliminó la raíz
00494        {     // En este caso, los factores quedan inalterados y no se viola 
00495              // la condición AVL   
00496          clean_avl_stack();
00497 
00498          return p;
00499        }
00500 
00501     restore_avl_after_deletion(removed_key);
00502 
00503     return p;
00504   }
00505 };
00506 
00523     template <typename Key, class Compare = Aleph::less<Key> >
00524 class Avl_Tree : public Gen_Avl_Tree<AvlNode, Key, Compare>
00525 { /* empty */ };
00526 
00543     template <typename Key, class Compare = Aleph::less<Key> >
00544 class Avl_Tree_Vtl : public Gen_Avl_Tree<AvlNodeVtl, Key, Compare>
00545 { /* empty */ };
00546 
00547 } // end namespace Aleph
00548 # endif // TPL_AVL_H
00549 

Leandro R. León