tpl_rand_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_RAND_TREE_H
00045 # define TPL_RAND_TREE_H
00046 
00047 # include <limits.h>
00048 # include <gsl/gsl_rng.h>
00049 # include <ahUtils.H>
00050 # include <ahFunction.H>
00051 # include <tpl_randNode.H>
00052 # include <tpl_binNodeUtils.H>
00053 
00054 using namespace Aleph;
00055 
00056 namespace Aleph { 
00057 
00077     template <template <typename> class NodeType, typename Key, class Compare>
00078 class Gen_Rand_Tree
00079 {
00080 
00081 public:
00082 
00084   typedef NodeType<Key> Node;
00085 
00086 private:
00087 
00088   Node *    tree_root; 
00089   gsl_rng * r;
00090   Gen_Rand_Tree(const Gen_Rand_Tree&);
00091 
00092   Gen_Rand_Tree& operator = (const Gen_Rand_Tree&);
00093 
00094 public:
00095 
00097   gsl_rng * gsl_rng_object() { return r;}
00100   Gen_Rand_Tree() : tree_root(Node::NullPtr), r(NULL)
00101   {
00102     r = gsl_rng_alloc (gsl_rng_mt19937);
00103 
00104     if (r == NULL)
00105       throw std::bad_alloc();
00106 
00107     gsl_rng_set(r, time(NULL) % gsl_rng_max(r));
00108   }
00109 
00111   virtual ~Gen_Rand_Tree() 
00112   {
00113     if (r != NULL)
00114       gsl_rng_free(r);
00115   }
00139   Node * random_insert(Node * root, Node * node)
00140   {
00141     if (root == Node::NullPtr)
00142       return node;
00143 
00144     const long & n = COUNT(root); 
00145 
00146     const size_t rn = gsl_rng_uniform_int(r, n + 1);;
00147 
00148     if (rn == n) // ¿Gana node el sorteo de ser raíz?
00149       return insert_root_xt<Node, Compare> (root, node); // sí, node será raíz
00150 
00151     Node * result;
00152     if (Compare() (KEY(node), KEY(root))) // ¿insertar en árbol izquierdo?
00153       {
00154         result = random_insert(LLINK(root), node); // inserta en rama izquierda
00155 
00156         if (result != Node::NullPtr) // ¿hubo inserción?
00157           {    // si ==> actualizar rama y contadores
00158             LLINK(root) = result;
00159             ++COUNT(root); 
00160           }
00161       }
00162     else if (Compare() (KEY(root), KEY(node)))// ¿insertar en árbol derecho?
00163       {
00164         result = random_insert(RLINK(root), node); // inserta en rama derecha
00165 
00166         if (result != Node::NullPtr) // ¿hubo inserción?
00167           {    // si ==> actualizar rama y contadores
00168             RLINK(root) = result;
00169             ++COUNT(root); 
00170           }
00171       }
00172     else
00173       return Node::NullPtr; // clave duplicada ==> no hay inserción
00174 
00175     return root;
00176   }
00186   Node * insert(Node * p)
00187   {
00188 
00189     I(p != Node::NullPtr);
00190     I((LLINK(p) == Node::NullPtr) and (RLINK(p) == Node::NullPtr));
00191     I(COUNT(p) == 1);
00192 
00193     Node * result = random_insert(tree_root, p);
00194 
00195     if (result == Node::NullPtr)
00196       return NULL;
00197 
00198     tree_root = result;
00199 
00200     return p;
00201   }
00227   Node * random_join_exclusive(Node * tl, Node * tr)
00228   {
00229     if (tl == Node::NullPtr)
00230       return tr;
00231 
00232     if (tr == Node::NullPtr)
00233       return tl;
00234 
00235     const size_t & m = COUNT(tl);
00236     const size_t & n = COUNT(tr);
00237 
00238     const size_t rn = 1 + gsl_rng_uniform_int(r, m + n);  
00239     
00240     if (rn <= m) 
00241       {    // rama izquierda gana sorteo
00242         COUNT(tl) += COUNT(tr);
00243         RLINK(tl) = random_join_exclusive(RLINK(tl), tr);
00244 
00245         return tl;
00246       }
00247     else 
00248       {
00249         COUNT(tr) += COUNT(tl);
00250         LLINK(tr) = random_join_exclusive(tl, LLINK(tr));
00251 
00252         return tr;
00253       }
00254   }
00278   Node * random_remove(Node *& root, const Key & key)
00279   {
00280     if (root == Node::NullPtr)
00281       return Node::NullPtr;
00282 
00283     Node * ret_val;
00284 
00285     if (Compare() (key, KEY(root)))
00286       {
00287         ret_val = random_remove(LLINK(root), key);
00288 
00289         if (ret_val != Node::NullPtr)
00290           COUNT(root)--;
00291 
00292         return ret_val;
00293       }
00294     else if (Compare() (KEY(root), key))
00295       {
00296         ret_val = random_remove(RLINK(root), key);
00297 
00298         if (ret_val != Node::NullPtr)
00299           COUNT(root)--;
00300 
00301         return ret_val;
00302       }
00303     
00304         // clave encontrada
00305     ret_val = root;
00306     root = random_join_exclusive(LLINK(root), RLINK(root));
00307     ret_val->reset();
00308 
00309     return ret_val;
00310   }
00322   Node * remove(const Key & key)
00323   {
00324     Node * ret_val = random_remove(tree_root, key);
00325 
00326     return ret_val != Node::NullPtr ? ret_val : NULL;
00327   }
00329   Node * search(const Key & key)
00330   {
00331     Node * retVal = searchInBinTree<Node, Compare>(tree_root, key);
00332 
00333     return retVal == Node::NullPtr ? NULL : retVal;
00334   }
00335 
00338   Node *& getRoot() { return tree_root; }
00339 
00340 };
00341 
00362     template <typename Key, class Compare = Aleph::less<Key> >
00363 class Rand_Tree : public Gen_Rand_Tree<RandNode, Key, Compare>
00364     { /* empty */ };
00365 
00386     template <typename Key, class Compare = Aleph::less<Key> >
00387 class Rand_Tree_Vtl : public Gen_Rand_Tree<RandNodeVtl, Key, Compare>
00388     { /* empty */ };
00389 
00390 } // end namespace Aleph
00391 
00392 # endif // TPL_RAND_TREE_H 
00393 

Leandro R. León