tpl_splay_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_SPLAY_TREE_H
00045 # define TPL_SPLAY_TREE_H
00046 
00047 # include <tpl_binNode.H>
00048 # include <tpl_binNodeUtils.H>
00049 # include <tpl_arrayStack.H> 
00050 
00051 using namespace Aleph;
00052 
00053 namespace Aleph {
00054 
00075     template <template <typename> class NodeType, typename Key, class Compare> 
00076 class Gen_Splay_Tree 
00077 {
00078 
00079 public:
00080 
00081   typedef NodeType<Key> Node;
00082 
00083 private:
00084 
00085   Gen_Splay_Tree(const Gen_Splay_Tree&);
00086 
00087   Gen_Splay_Tree& operator = (const Gen_Splay_Tree&);
00088 
00089   static Node * zig_zig_right(Node* p)
00090   {
00091     Node * q = LLINK(p);
00092     Node * r = LLINK(q);
00093     LLINK(p) = RLINK(q);
00094     LLINK(q) = RLINK(r);
00095     RLINK(q) = p;
00096     RLINK(r) = q;
00097 
00098     return r;
00099   }
00100 
00101   static Node * zig_zig_left(Node* p)
00102   {
00103     Node * q = RLINK(p);
00104     Node * r = RLINK(q);
00105     RLINK(p) = LLINK(q);
00106     RLINK(q) = LLINK(r);
00107     LLINK(q) = p;
00108     LLINK(r) = q;
00109 
00110     return r;
00111   }
00112 
00113   static Node * zig_zag_right(Node* p)
00114   {
00115     LLINK(p) = rotate_to_left(LLINK(p));
00116     return rotate_to_right(p);
00117   } 
00118 
00119   static Node * zig_zag_left(Node* p)
00120   {
00121     RLINK(p) = rotate_to_right(RLINK(p));
00122     return rotate_to_left(p);
00123   } 
00124 
00125 
00126   struct Node_Desc
00127   {
00128     Node *  node;
00129     Node ** node_parent;
00130 
00131     Node_Desc() { /* empty */ }
00132 
00133     Node_Desc(Node * p, Node ** pp) : node(p), node_parent(pp) { /* empty */ }
00134 
00135   };
00136   ArrayStack<Node_Desc, Node::MaxHeight> splay_stack;
00137   void push_in_splay_stack(Node * p, Node ** pp)
00138   {
00139     try 
00140       {
00141         splay_stack.push(Node_Desc(p, pp));
00142       }
00143     catch (std::overflow_error) 
00144       {
00145         splay_stack.empty();
00146         throw;
00147       }
00148   }    
00149   void search_and_push_in_splay_stack(const Key & key) 
00150   {
00151     splay_stack.empty();
00152 
00153     Node ** pp = &RLINK(head);
00154     Node * p   = root;
00155       
00156     while (p != NULL) // buscar iterativamente key
00157       {
00158         push_in_splay_stack(p, pp);
00159    
00160         if (Compare()(key, KEY(p)))
00161           {
00162             pp = &LLINK(p); 
00163             p  = LLINK(p); 
00164           }
00165         else if (Compare()(KEY(p), key))
00166           {
00167             pp = &RLINK(p); 
00168             p  = RLINK(p); 
00169           }
00170         else
00171           return;
00172       }
00173   }
00174   Node  head_node;  
00175   Node  *head;     
00176   Node *&root;
00177   enum Zig_Type { ZIG_LEFT, ZIG_RIGHT, ZIG_ZAG_LEFT, ZIG_ZAG_RIGHT, 
00178                   ZIG_ZIG_LEFT, ZIG_ZIG_RIGHT };
00179 
00180   Zig_Type zig_type(Node *& p, Node **& pp) 
00181   { 
00182 
00183     I(splay_stack.size() >= 2);
00184 
00185     Node_Desc first  = splay_stack.pop();
00186     Node_Desc second = splay_stack.pop();
00187     
00188     Zig_Type ret_val = 
00189       Compare()(KEY(second.node), KEY(first.node)) ? ZIG_LEFT : ZIG_RIGHT; 
00190        
00191     if (splay_stack.is_empty())
00192       { /* última etapa y es un zig */
00193         p  = second.node;
00194         pp = second.node_parent;
00195 
00196         return ret_val;
00197       }
00198    
00199     Node_Desc third = splay_stack.pop();
00200        
00201     pp = third.node_parent;
00202     p  = third.node;
00203     
00204     if (ret_val == ZIG_LEFT)
00205       return Compare()(KEY(third.node), KEY(second.node)) 
00206         ? ZIG_ZIG_LEFT : ZIG_ZAG_RIGHT;
00207 
00208     return Compare()(KEY(second.node), KEY(third.node))
00209       ? ZIG_ZIG_RIGHT : ZIG_ZAG_LEFT;
00210   }
00211   void splay()
00212   {
00213     if (splay_stack.is_empty() or splay_stack.top().node == root)
00214       return;
00215 
00216     Node **pp, *p; 
00217     while (true)
00218       {
00219         switch (zig_type(p, pp))
00220           {
00221           case ZIG_LEFT:      *pp = rotate_to_left(p);  break;
00222           case ZIG_RIGHT:     *pp = rotate_to_right(p); break;
00223           case ZIG_ZIG_LEFT:  *pp = zig_zig_left(p);  break;
00224           case ZIG_ZIG_RIGHT: *pp = zig_zig_right(p); break;
00225           case ZIG_ZAG_LEFT:  *pp = zig_zag_left(p);  break;
00226           case ZIG_ZAG_RIGHT: *pp = zig_zag_right(p); break;
00227 
00228           default: ERROR("Invalid rotation type");
00229 
00230           }
00231         
00232         if (splay_stack.is_empty())
00233           break;
00234 
00235         push_in_splay_stack(p, pp);
00236       }
00237   }
00238 
00239 public:
00240 
00241   virtual ~Gen_Splay_Tree() { /* empty */ }
00242 
00244   Node*& getRoot() const { return root; }
00245 
00246   Gen_Splay_Tree() : head(&head_node), root(RLINK(head)) { /* Empty */ }
00250   Node * search(const Key & key)
00251   {
00252     if (root == NULL)
00253       return NULL;
00254 
00255     search_and_push_in_splay_stack(key);
00256 
00257     splay();
00258 
00259     if (are_equals<Key, Compare>(key, KEY(root)))
00260       return root;
00261 
00262     return NULL;
00263   }
00268   Node * insert(Node * p)
00269   {
00270     if (root == NULL)
00271       { 
00272         root = p;
00273         return root;
00274       }
00275 
00276     search_and_push_in_splay_stack(KEY(p)); 
00277 
00278     Node * pp = splay_stack.top().node;
00279 
00280         // meter p en la pila
00281     if (Compare()(KEY(p), KEY(pp))) 
00282       {
00283         LLINK(pp) = p;
00284         push_in_splay_stack(p, &LLINK(pp));
00285       }
00286     else if (Compare()(KEY(pp), KEY(p)))
00287       {
00288         RLINK(pp) = p;
00289         push_in_splay_stack(p, &RLINK(pp));
00290       }
00291     else
00292       {     // clave duplicada
00293         splay(); // de todos modos hacemos el splay
00294         
00295         return NULL; 
00296       }
00297 
00298     splay();
00299 
00300     return root;
00301   }
00305   Node * remove(const Key & key)
00306   {
00307     search_and_push_in_splay_stack(key);
00308 
00309     splay(); // Suba el nodo hasta la raíz mediante el splay
00310    
00311     if (no_equals<Key, Compare>(KEY(root), key)) // ¿se encontró key?
00312       return NULL; // no
00313 
00314     Node * p = root;
00315     root = join_exclusive(LLINK(root), RLINK(root)); 
00316     p->reset();
00317 
00318     return p;
00319   }
00320 };
00321 
00335     template <typename Key, class Compare = Aleph::less<Key> >
00336 struct Splay_Tree : public Gen_Splay_Tree<BinNode, Key, Compare>
00337 { /* Empty */ };
00338 
00352     template <typename Key, class Compare = Aleph::less<Key> >
00353 struct Splay_Tree_Vtl : public Gen_Splay_Tree<BinNodeVtl, Key, Compare>
00354 { /* Empty */ };
00355 
00356 
00357 } // end namespace Aleph
00358 # endif /* TPL_SPLAY_TREE_H */
00359 

Leandro R. León