tpl_binNodeXt.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_BINNODEXT_H
00045 # define TPL_BINNODEXT_H
00046 
00047 # include <tpl_binNode.H>
00048 # include <tpl_binNodeUtils.H>
00049 
00050 using namespace Aleph;
00051 
00052 namespace Aleph {
00053 
00054 class BinNodeXt_Data
00055 {
00056   size_t count; // cardinalidad del árbol
00057 
00058 public:
00059 
00060   BinNodeXt_Data() : count(1) { /* empty */ }
00061   BinNodeXt_Data(SentinelCtor) : count(0) { /* empty */ }
00062   size_t & getCount() { return count; }
00063   const size_t & size() const { return count; }
00064   void reset() { count = 1; }
00065 };
00066 
00067 DECLARE_BINNODE_SENTINEL(BinNodeXt, 255, BinNodeXt_Data);
00068 
00074 # define COUNT(p) ((p)->getCount())
00075 
00092     template <class Node> inline 
00093 Node * select_rec(Node * r, const size_t & i) 
00094 
00095   throw(std::exception, std::out_of_range) 
00096 
00097 { 
00098 
00099   I(r != Node::NullPtr);
00100   I(COUNT(Node::NullPtr) == 0);
00101 
00102   if (i >= COUNT(r))
00103     throw std::out_of_range("infix position out of range");
00104 
00105   if (i == COUNT(LLINK(r)))
00106     return r;
00107 
00108   if (i < COUNT(LLINK(r)))
00109     return select_rec(static_cast<Node*>(LLINK(r)), i);
00110 
00111   return select_rec(static_cast<Node*>(RLINK(r)), i - COUNT(LLINK(r)) - 1);
00112 }
00130     template <class Node> inline
00131 Node * select(Node * r, const size_t & pos) 
00132 
00133   throw(std::exception, std::out_of_range)
00134 
00135 {
00136 
00137   I(COUNT(Node::NullPtr) == 0);
00138 
00139   if (pos >= COUNT(r))
00140     throw std::out_of_range("infix position out of range");
00141 
00142 
00143   for (size_t i = pos; i != COUNT(LLINK(r)); /* nada */)
00144 
00145     {
00146       I(i < COUNT(r));
00147 
00148       if (i < COUNT(LLINK(r)))
00149         r = static_cast<Node*>(LLINK(r)); 
00150       else
00151         {
00152           i -= COUNT(LLINK(r)) + 1;
00153           r = static_cast<Node*>(RLINK(r));
00154         }
00155 
00156     }
00157 
00158   return r;
00159 }
00183     template <class Node, class Compare> inline
00184 size_t inorder_position(Node *                          r,
00185                         const typename Node::key_type & key, 
00186                         Node *&                         node)
00187 {
00188 
00189   I(COUNT(Node::NullPtr) == 0);
00190 
00191   if (r == Node::NullPtr)
00192     throw std::domain_error("Key not found");
00193 
00194 
00195   if (Compare () (key, KEY(r))) 
00196     return inorder_position(static_cast<Node*>(LLINK(r)), key, node);
00197   else if (Compare () (KEY(r), key)) 
00198     return inorder_position(static_cast<Node*>(RLINK(r)), key, node) + 
00199       COUNT(LLINK(r)) + 1;
00200   else
00201     return COUNT(LLINK(r));
00202 }
00203     template <class Node> inline
00204 int inorder_position(Node *                          r, 
00205                      const typename Node::key_type & key, 
00206                      Node *&                         node)
00207 {
00208   return 
00209     inorder_position<Node, Aleph::less<typename Node::key_type> >(r, key, node);
00210 }
00229     template <class Node, class Compare> inline
00230 Node * insert_by_key_xt(Node *& r, Node * p)
00231 {
00232 
00233   I(COUNT(Node::NullPtr) == 0);
00234 
00235   if (r == Node::NullPtr)
00236     return r = p;
00237 
00238   Node * q;
00239 
00240   if (Compare () (KEY(p), KEY(r)))
00241     {
00242       q = insert_by_key_xt<Node, Compare>(static_cast<Node*&>(LLINK(r)), p);
00243 
00244       if (q != Node::NullPtr)
00245         ++COUNT(r); 
00246     }
00247   else if (Compare ()(KEY(r), KEY(p)))
00248     {
00249       q = insert_by_key_xt<Node, Compare>(static_cast<Node*&>(RLINK(r)), p);
00250 
00251       if (q != Node::NullPtr)
00252         ++COUNT(r); 
00253     }
00254   else
00255     return (Node*) Node::NullPtr; // clave duplicada
00256 
00257   return q;
00258 }
00259     template <class Node> inline
00260 Node * insert_by_key_xt(Node *& root, Node * p)
00261 {
00262   return insert_by_key_xt<Node, Aleph::less<typename Node::key_type> >(root, p);
00263 }
00264 # define SPLIT split_key_rec_xt<Node, Compare>
00265 
00287     template <class Node, class Compare> inline
00288 bool split_key_rec_xt(Node * root, const typename Node::key_type & key, 
00289                       Node *& l, Node *& r)
00290 {
00291   if (root == Node::NullPtr)
00292     {
00293       l = r = Node::NullPtr;
00294 
00295       return true;
00296     }
00297 
00298   if (Compare() (key, KEY(root)))
00299     {
00300       if (not SPLIT(LLINK(root), key, l, LLINK(root)))
00301         return false;
00302 
00303       r = root;
00304       COUNT(r) -= COUNT(l);
00305     }
00306   else if (Compare() (KEY(root), key))
00307     {
00308       if (not SPLIT(RLINK(root), key, RLINK(root), r))
00309         return false;
00310 
00311       l = root;
00312       COUNT(l) -= COUNT(r);
00313     }
00314   else
00315     return false; // clave duplicada
00316 
00317   return true;
00318 }
00319 # undef SPLIT
00320 
00321     template <class Node> inline
00322 bool split_key_rec_xt(Node * root, const typename Node::key_type & key, 
00323                       Node *& l, Node *& r)
00324 {
00325   return 
00326     split_key_rec_xt<Node, Aleph::less<typename Node::key_type> >(root, key, 
00327                                                                   l, r);
00328 }
00346     template <class Node, class Compare> inline
00347 Node * insert_root_xt(Node *& root, Node * p)
00348 {
00349   if (root == Node::NullPtr) 
00350     return p;
00351 
00352   if (not split_key_rec_xt<Node, Compare>(root, KEY(p), LLINK(p), RLINK(p)))
00353     return Node::NullPtr;
00354 
00355   COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
00356 
00357   root = p;
00358 
00359   return p; 
00360 }
00381     template <class Node> inline
00382 void split_pos_rec(Node * r, const size_t & i, Node *& ts, Node *& tg)
00383 {
00384 
00385   if (i > COUNT(r))
00386     throw std::out_of_range("infix position out of range");
00387 
00388   if (i == COUNT(r)) // ¿Es la última posición (que está vacía)?
00389     {
00390       ts = r;
00391       tg = Node::NullPtr;
00392 
00393       return;
00394     }
00395 
00396   if (i == COUNT(LLINK(r))) // ¿se alcanzó la posición de partición?
00397     {
00398       ts = LLINK(r);
00399       tg = r;
00400       LLINK(tg) = Node::NullPtr;
00401       COUNT(tg) -= COUNT(ts);
00402 
00403       return;
00404     }
00405 
00406   if (i < COUNT(LLINK(r)))
00407     {
00408       split_pos_rec(static_cast<Node*>(LLINK(r)), i, ts, 
00409                     static_cast<Node*&>(LLINK(r)));
00410       tg = r;
00411       COUNT(r) -= COUNT(ts);
00412     }
00413   else
00414     {
00415       split_pos_rec(static_cast<Node*>(RLINK(r)), i - (COUNT(LLINK(r)) + 1), 
00416                     static_cast<Node*&>(RLINK(r)), tg);
00417       ts = r;
00418       COUNT(r) -= COUNT(tg);
00419     }
00420 }
00435     template <class Node>  inline
00436 void insert_by_pos_xt(Node *& r, Node * p, const size_t & pos)
00437 {
00438 
00439   I(COUNT(Node::NullPtr) == 0);
00440 
00441   split_pos_rec(r, pos, static_cast<Node*&>(LLINK(p)),
00442                 static_cast<Node*&>(RLINK(p)));
00443 
00444   COUNT(p) = COUNT(LLINK(p)) + 1 + COUNT(RLINK(p));
00445 
00446   r = p;
00447 }
00463     template <class Node> inline
00464 Node * join_exclusive_xt(Node *& ts, Node *& tg)
00465 {
00466   if (ts == Node::NullPtr)
00467     return tg;
00468 
00469   if (tg == Node::NullPtr)
00470     return ts;
00471 
00472   LLINK(tg) = join_exclusive_xt(RLINK(ts), LLINK(tg));
00473   RLINK(ts) = tg;
00474 
00475   COUNT(tg) = COUNT(LLINK(tg)) + 1 + COUNT(RLINK(tg)); // actualizar contadores
00476   COUNT(ts) = COUNT(LLINK(ts)) + 1 + COUNT(RLINK(ts));
00477 
00478   Node * ret_val = ts;
00479 
00480   ts = tg = Node::NullPtr; // deben quedar vacíos después del join
00481 
00482   return ret_val;
00483 }  
00484 # define REMOVE remove_by_key_xt<Node, Compare>
00485 
00503     template <class Node, class Compare> inline
00504 Node * remove_by_key_xt(Node *& root, const typename Node::key_type & key)
00505 {
00506 
00507   I(root != Node::NullPtr);
00508 
00509   if (root == Node::NullPtr)
00510     return (Node*) Node::NullPtr; // clave no encontrada
00511 
00512   Node * ret_val = Node::NullPtr; 
00513 
00514   if (Compare () (key, KEY(root)))
00515     {
00516       ret_val = REMOVE(static_cast<Node*&>(LLINK(root)), key);
00517 
00518       if (ret_val != Node::NullPtr) // ¿hubo eliminación?
00519         --COUNT(root); // Sí ==> actualizar contador
00520     
00521       return ret_val;
00522     }
00523   else if (Compare () (KEY(root), key))
00524     {
00525       ret_val = REMOVE(static_cast<Node*&>(RLINK(root)), key);
00526 
00527       if (ret_val != Node::NullPtr) // ¿hubo eliminación?
00528         --COUNT(root); // Sí ==> actualizar contador
00529     
00530       return ret_val;
00531     }
00532 
00533   ret_val = root; // clave encontrada ==> eliminar
00534 
00535   root = join_exclusive_xt(static_cast<Node*&>(LLINK(root)),
00536                            static_cast<Node*&>(RLINK(root)));
00537 
00538   ret_val->reset();
00539 
00540 
00541   return ret_val;
00542 }
00543 # undef REMOVE
00544 
00545     template <class Node> inline
00546 Node * remove_by_key_xt(Node *& root, const typename Node::key_type & key)
00547 {
00548   I(root != Node::NullPtr);
00549 
00550   return remove_by_key_xt<Node, Aleph::less<typename Node::key_type> >
00551     (root, key);
00552 }
00569     template <class Node> inline
00570 Node * remove_by_pos_xt(Node *& root, const size_t & pos)
00571 {
00572 
00573   if (pos >= COUNT(root))
00574     throw std::out_of_range("infix position out of range");
00575 
00576   if (COUNT(LLINK(root)) == pos) // ¿posición encontrada?
00577     {     // Si ==> guarde nodo y realice join exclusivo
00578       Node * ret_val = root;
00579 
00580       root = join_exclusive_xt(static_cast<Node*&>(LLINK(root)), 
00581                                static_cast<Node*&>(RLINK(root)));
00582 
00583       ret_val->reset();
00584 
00585       return ret_val;
00586     }
00587 
00588   Node * ret_val; // guarda valor de retorno de llamada recursiva
00589 
00590   if (pos < COUNT(LLINK(root)))
00591     ret_val = remove_by_pos_xt(static_cast<Node*&>(LLINK(root)), pos);
00592   else
00593     ret_val = remove_by_pos_xt(static_cast<Node*&>(RLINK(root)), 
00594                                pos - (COUNT(LLINK(root)) + 1));
00595 
00596   if (ret_val != Node::NullPtr) // ¿hubo eliminación?
00597     --COUNT(root); // Si ==> el árbol con raíz root perdió un nodo
00598 
00599   return ret_val;
00600 }  
00601     template <class Node> inline
00602 bool check_rank_tree(Node * root)
00603 {
00604   if (root == Node::NullPtr)
00605     return true;
00606 
00607   if (COUNT(LLINK(root)) + COUNT(RLINK(root)) + 1 != COUNT(root))
00608     return false;
00609 
00610   return check_rank_tree(LLINK(root)) and check_rank_tree(RLINK(root));
00611 }
00616     template <class Node> inline
00617 Node * rotate_to_right_xt(Node* p)
00618 {
00619 
00620   I(p != Node::NullPtr);
00621 
00622   Node * q  = static_cast<Node*>(LLINK(p));
00623   LLINK(p) = RLINK(q);
00624   RLINK(q) = p;
00625   COUNT(p) -= 1 + COUNT(LLINK(q));
00626   COUNT(q) += 1 + COUNT(RLINK(p));
00627   return q;           
00628 } 
00633     template <class Node> inline
00634 Node * rotate_to_left_xt(Node* p)
00635 {
00636   I(p != Node::NullPtr);
00637 
00638   Node * q  = static_cast<Node*>(RLINK(p));
00639   RLINK(p) = LLINK(q);
00640   LLINK(q) = p;
00641 
00642   COUNT(p) -= 1 + COUNT(RLINK(q));
00643   COUNT(q) += 1 + COUNT(LLINK(p));
00644 
00645   return q;                  
00646 } 
00647 
00648 } // end namespace Aleph
00649 
00650 # endif // TPL_BINNODEXT_H
00651 

Leandro R. León