tpl_binNodeUtils.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_BINNODEUTILS_H
00045 # define TPL_BINNODEUTILS_H 
00046 
00047 # include <ahFunction.H>
00048 # include <ahPair.H>
00049 # include <tpl_arrayStack.H> 
00050 # include <tpl_arrayQueue.H>
00051 # include <tpl_dynArray.H>
00052 # include <tpl_dynDlist.H>
00053 # include <tpl_binNode.H>
00054 
00055 using namespace Aleph;
00056 namespace Aleph {
00057 
00058     template <class Node> inline static
00059 void __inorder_rec(Node *node, const int& level, int & position, 
00060                    void (*visitFct)(Node*, int, int))
00061 {
00062   if (node == Node::NullPtr) 
00063     return;
00064 
00065   __inorder_rec(static_cast<Node*>(LLINK(node)), 
00066                 level + 1, position, visitFct);
00067   (*visitFct)(node, level, position);
00068   ++position;
00069   __inorder_rec(static_cast<Node*>(RLINK(node)),
00070                 level + 1, position, visitFct); 
00071 }
00093     template <class Node> inline
00094 int inOrderRec(Node * root, void (*visitFct)(Node*, int, int))
00095 {
00096   int position = 0;
00097   
00098   __inorder_rec(root, 0, position, visitFct); 
00099 
00100   return position;
00101 }
00102     template <class Node> inline static
00103 void __preorder_rec (Node *p, const int & level, int & position,
00104                      void (*visitFct)(Node*, int, int))
00105 {
00106   if (p == Node::NullPtr) 
00107     return;
00108 
00109   (*visitFct)(p, level, position);
00110   ++position;
00111 
00112   __preorder_rec(static_cast<Node*>(LLINK(p)), 
00113                  level + 1, position, visitFct);
00114   __preorder_rec(static_cast<Node*>(RLINK(p)), 
00115                  level + 1, position, visitFct);
00116 } 
00117 
00140     template <class Node> inline 
00141 int preOrderRec(Node * root, void (*visitFct)(Node*, int, int))
00142 {
00143   int position = 0;
00144   
00145   __preorder_rec(root, 0, position, visitFct); 
00146 
00147   return position;
00148 }
00149 
00150     template <class Node> inline static
00151 void __postorder_rec(Node *node, const int & level, int & position, 
00152                      void (*visitFct)(Node*, int, int))
00153 {
00154   if (node == Node::NullPtr) 
00155     return;
00156 
00157   __postorder_rec(static_cast<Node*>(LLINK(node)), 
00158                   level + 1, position, visitFct);
00159   __postorder_rec(static_cast<Node*>(RLINK(node)), 
00160                   level + 1, position, visitFct); 
00161 
00162   (*visitFct)(node, level, position);
00163   ++position;
00164 }
00165 
00187     template <class Node> inline
00188 int postOrderRec(Node * root, void (*visitFct)(Node*, int, int))
00189 {
00190   int position = 0;
00191   
00192   __postorder_rec(root, 0, position, visitFct); 
00193 
00194   return position;
00195 }
00222     template <class Node> inline
00223 size_t simple_preOrderStack(Node * node, void (*visitFct)(Node *, int, int))
00224 {
00225   if (node == Node::NullPtr) 
00226     return 0;
00227 
00228   ArrayStack<Node *, Node::MaxHeight> stack;
00229 
00230   stack.push(node); 
00231 
00232   Node * p;
00233 
00234   size_t count = 0;
00235 
00236   while (not stack.is_empty())
00237     {
00238       p = stack.pop();
00239 
00240       (*visitFct) (p, stack.size(), count++); 
00241 
00242       if (RLINK(p) != Node::NullPtr)
00243         stack.push(RLINK(p));
00244 
00245       if (LLINK(p) != Node::NullPtr)
00246         stack.push(LLINK(p));
00247     }
00248 
00249   return count;
00250 } 
00277     template <class Node> inline
00278 size_t preOrderStack(Node * node, void (*visitFct)(Node *, int, int))
00279 {
00280   if (node == Node::NullPtr) 
00281     return 0;
00282 
00283   ArrayStack<Node *, Node::MaxHeight> stack;
00284   Node *p = node;
00285 
00286   size_t count = 0;
00287 
00288   while (true)
00289     {
00290       (*visitFct)(p, stack.size(), count++);
00291 
00292       if (LLINK(p) != Node::NullPtr)
00293         {
00294           stack.push(p); // push porque p y RLINK(p) faltan por visitarse
00295           p = LLINK(p);  // avanzar a la izquierda
00296 
00297           continue; // ir a visitar raíz rama izquierda
00298         }
00299       
00300       while (true) 
00301         {
00302           if (RLINK(p) != Node::NullPtr)
00303             {
00304               p = RLINK(p); // avanzar a la derecha
00305               break;        // ir a visitar raíz rama derecha
00306             }
00307 
00308           if (stack.is_empty()) 
00309             return count; // fin
00310 
00311           p = stack.pop(); // sacar para ir a rama derecha
00312         }
00313     }
00314 }
00340     template <class Node> inline
00341 size_t inOrderStack(Node * node, void (*visitFct)(Node *, int, int))
00342 {
00343   if (node == Node::NullPtr) 
00344     return 0;
00345 
00346   ArrayStack<Node *, Node::MaxHeight> stack;
00347   Node *p = node;
00348 
00349   size_t count = 0;
00350 
00351   while (true)
00352     {
00353       if (LLINK(p) != Node::NullPtr)
00354         {
00355           stack.push(p); // push porque p y RLINK(p) faltan por visitarse
00356           p = LLINK(p);  // avanzar a la izquierda
00357 
00358           continue; // continuar bajando por la rama izquierda
00359         }
00360       while (true)
00361         {
00362           (*visitFct)(p, stack.size(), count++);
00363 
00364           if (RLINK(p) != Node::NullPtr)
00365             {
00366               p = RLINK(p); // avanzar a la derecha
00367               break;        // ir a visitar raíz rama derecha
00368             }
00369 
00370           if (stack.is_empty()) 
00371             return count;
00372 
00373           p = stack.pop(); // sacar para ir a rama derecha
00374         }
00375     }
00376 }
00377     template <class Node> inline
00378 size_t postOrderStack(Node * root, void (*visitFct)(Node *, int, int))
00379 {    
00380   if (root == Node::NullPtr) 
00381     return 0;
00382 
00383   typedef Aleph::pair<Node*, char> Postorder_Pair;
00384   ArrayStack<Postorder_Pair, Node::MaxHeight> stack;
00385 
00386   Postorder_Pair __pair;
00387 
00388   Node *& p   = __pair.first  = root;
00389   char & side = __pair.second = 'i';
00390 
00391   stack.push(__pair);
00392 
00393   size_t count = 0;
00394 
00395   while (not stack.is_empty())
00396     {
00397       __pair = stack.pop();
00398 
00399       switch (side)
00400         {
00401         case 'i': 
00402           if (LLINK(p) != Node::NullPtr)
00403             stack.push(Postorder_Pair(LLINK(p), 'i'));
00404 
00405           stack.push(Postorder_Pair(p, 'l'));
00406 
00407           break;
00408         case 'l':
00409           if (RLINK(p) != Node::NullPtr)
00410             stack.push(Postorder_Pair(RLINK(p), 'i'));
00411 
00412           stack.push(Postorder_Pair(p, 'r'));
00413           
00414           break;
00415         case 'r':
00416           (*visitFct) (p, stack.size(), count++); 
00417 
00418           break;
00419         }
00420     }
00421 
00422   return count;
00423 }
00433     template <class Node> inline
00434 size_t compute_cardinality_rec(Node * node)
00435 {
00436   if (node == Node::NullPtr) 
00437     return 0;
00438 
00439   return (compute_cardinality_rec(LLINK(node)) + 1 + 
00440           compute_cardinality_rec(RLINK(node)));
00441 }
00451     template <class Node> inline
00452 size_t computeHeightRec(Node * node)
00453 {
00454   if (node == Node::NullPtr) 
00455     return 0;
00456 
00457   const size_t left_height  = computeHeightRec(LLINK(node));
00458   const size_t right_height = computeHeightRec(RLINK(node));
00459 
00460   return 1 + Aleph::max(left_height, right_height);
00461 }
00472     template <class Node> inline 
00473 Node * copyRec(Node * src_root) throw(std::exception, std::bad_alloc) 
00474 {
00475   if (src_root == Node::NullPtr) 
00476     return (Node*) Node::NullPtr;
00477 
00478   Node * tgt_root = new Node(*src_root); 
00479 
00480   try 
00481     {
00482       LLINK(tgt_root) = copyRec<Node>(static_cast<Node*>(LLINK(src_root)));
00483       RLINK(tgt_root) = copyRec<Node>(static_cast<Node*>(RLINK(src_root)));
00484     }
00485   catch (...)
00486     {
00487 
00488       I(RLINK(tgt_root) == Node::NullPtr);
00489 
00490       if (LLINK(tgt_root) != Node::NullPtr) 
00491         destroyRec(LLINK(tgt_root)); // TODO: diff de Node*&
00492 
00493       delete tgt_root;
00494 
00495       throw;
00496     }
00497 
00498   return tgt_root;
00499 }      
00508     template <class Node> inline
00509 void destroyRec(Node * root)
00510 {
00511   if (root == Node::NullPtr) 
00512     return;
00513 
00514   destroyRec(static_cast <Node*> (LLINK(root)));
00515   destroyRec(static_cast <Node*> (RLINK(root)));
00516 
00517   delete root;
00518 }
00529     template <class Node> inline
00530 bool areSimilar(Node * t1, Node * t2)
00531 {
00532   if (t1 == Node::NullPtr and t2 == Node::NullPtr)
00533     return true;
00534 
00535   if (t1 == Node::NullPtr or t2 == Node::NullPtr)
00536     return false;
00537   
00538   return (areSimilar(LLINK(t1), LLINK(t2)) and
00539           areSimilar(RLINK(t1), RLINK(t2)));
00540 }
00559     template <class Node, class Equal> inline
00560 bool areEquivalents(Node * t1, Node * t2)
00561 {
00562   if (t1 == Node::NullPtr and t2 == Node::NullPtr)
00563     return true;
00564 
00565   if (t1 == Node::NullPtr or t2 == Node::NullPtr)
00566     return false;
00567   
00568   if (not Equal () (KEY(t1), KEY(t2)))
00569     return false;
00570 
00571   return (areEquivalents<Node, Equal>(LLINK(t1), LLINK(t2)) and 
00572           areEquivalents<Node, Equal>(RLINK(t1), RLINK(t2)));
00573 }
00574     template <class Node> inline
00575 bool areEquivalents(Node * t1, Node * t2)
00576 {
00577   return 
00578     areEquivalents<Node, Aleph::equal_to<typename Node::key_type> >(t1, t2);
00579 }
00610     template <class Node> inline
00611 void levelOrder(Node *         root, 
00612                 void           (*visitFct)(Node*, int, bool), 
00613                 const size_t & queue_size)
00614 {
00615   if (root == Node::NullPtr)
00616     return;
00617 
00618   const size_t two_power = 
00619     static_cast<size_t>(std::log((float)queue_size)/std::log(2.0) + 1);
00620 
00621   ArrayQueue<Aleph::pair<Node*, bool> > queue(two_power); 
00622 
00623   queue.put(root);
00624 
00625   for (int pos = 0; not queue.is_empty(); pos++)
00626     {
00627       Aleph::pair<Node*, bool> pr = queue.get();
00628 
00629       Node *& p = pr.first;
00630 
00631       (*visitFct) (p, pos, pr.second);
00632 
00633       if (LLINK(p) != Node::NullPtr)
00634         queue.put(Aleph::pair <Node*, bool> (LLINK(p), true));
00635 
00636       if (RLINK(p) != Node::NullPtr)
00637         queue.put(Aleph::pair <Node*, bool> (RLINK(p), false));
00638     }
00639 }
00662     template <template <class> class Node, typename Key> inline
00663 Node<Key> * build_tree(DynArray<Key> & preorder, 
00664                        const int & l_p, const int & r_p,
00665                        DynArray<Key> & inorder, 
00666                        const int & l_i, const int & r_i)
00667 {
00668   if (l_p > r_p) // ¿está vacío el recorrido?
00669 
00670     { // sí, retornar árbol vacío
00671     I(l_i > r_i);
00672 
00673     return Node <Key> ::NullPtr;
00674 
00675     }
00676 
00677   I(r_p - l_p == r_i - l_i); 
00678 
00679 
00680   Node<Key> * root = new Node <Key> (preorder[l_p]); // crear la raíz
00681 
00682   if (r_p == l_p) // ¿recorrido de longitud 1?
00683     return root; // sí ==> no hay infijo a buscar
00684 
00685   
00686   I(l_i <= r_i);
00687 
00688   int i = 0;
00689   for (int j = l_i; j <= r_i; ++j)
00690     if (inorder[j] == preorder[l_p])
00691       {
00692         i = j - l_i;
00693         break;
00694       }
00695 
00696   I(i <= r_i);
00697 
00698 
00699   LLINK(root) = build_tree <Node, Key> (preorder, l_p + 1, l_p + i, 
00700                                         inorder, l_i, l_i + (i - 1));
00701 
00702   RLINK(root) = build_tree <Node, Key> (preorder, l_p + i + 1, r_p,
00703                                         inorder, l_i + i + 1, r_i);
00704     
00705   return root;
00706 }
00707     template <class Node> inline static
00708 void __compute_nodes_in_level(Node *            root, 
00709                               const int &       level,
00710                               const int &       current_level, 
00711                               DynDlist<Node*> & level_list)
00712 {
00713   if (root == Node::NullPtr)
00714     return;
00715 
00716   if (level == current_level)
00717     {
00718       level_list.append(root);
00719 
00720       return; // no vale la pena descender más
00721     }
00722 
00723   __compute_nodes_in_level(LLINK(root), level, current_level + 1, level_list);
00724 
00725   __compute_nodes_in_level(RLINK(root), level, current_level + 1, level_list);
00726 }
00740     template <class Node> inline
00741 void compute_nodes_in_level(Node *          root, 
00742                             const int &     level, 
00743                             DynDlist<Node*>& list)
00744 {
00745   __compute_nodes_in_level(root, level, 0, list);
00746 }
00772     template <class Node> inline
00773 void inOrderThreaded(Node * root, void (*visitFct)(Node*))
00774 {
00775   if (root == Node::NullPtr) 
00776     return;
00777 
00778   Node *p = root, *r = Node::NullPtr, *q;
00779 
00780   while (p != Node::NullPtr)
00781     {
00782       q = LLINK(p); 
00783 
00784       if (q == Node::NullPtr) 
00785         { // No hay rama izq ==> visitar p
00786 
00787           (*visitFct)(p);  
00788 
00789           r = p;          
00790           p = RLINK(p);   
00791 
00792           continue;       
00793         }
00794 
00795           // avanzar hacia el nodo más a la derecha de la rama izquierda
00796       while (q != r and RLINK(q) != Node::NullPtr)
00797         q = RLINK(q);
00798 
00799       if (q != r) // tiene p un predecesor? 
00800         { // si ==> dejar un hilo para luego subir a visitar p
00801           RLINK(q) = p; // Aquí se coloca el hilo
00802           p = LLINK(p); // Seguir bajando por la izquierda
00803 
00804           continue;     
00805         }
00806 
00807       (*visitFct)(p);
00808 
00809       RLINK (q) = Node::NullPtr; // Borrar hilo
00810       r = p;            
00811       p = RLINK(p); // avanzar a la rama derecha
00812     }
00813 }
00839     template <class Node> inline
00840 void preOrderThreaded(Node * node, void (*visitFct)(Node*))
00841 {
00842   if (node == Node::NullPtr) 
00843     return;
00844 
00845   Node *p = node, *r = Node::NullPtr, *q;
00846 
00847   while (p != Node::NullPtr)
00848   {
00849     q = LLINK(p); 
00850 
00851     if (q == Node::NullPtr) 
00852       { 
00853         (*visitFct)(p);  
00854 
00855         r = p;
00856         p = RLINK(p);
00857 
00858         continue;    
00859       }
00860 
00861         // avanzar hacia el nodo más a la derecha de la rama izquierda
00862     while (q != r and RLINK(q) != Node::NullPtr)
00863       q = RLINK(q);
00864 
00865     if (q != r) 
00866       { 
00867         RLINK(q) = p;
00868 
00869         (*visitFct)(p);
00870 
00871         p = LLINK(p);
00872 
00873         continue;    
00874       }
00875 
00876     RLINK(q) = Node::NullPtr; /* delete thread */
00877     r = p;                  
00878     p = RLINK(p);       /* advance to right branch */
00879   }
00880 } 
00881     template <class Node> inline  static
00882 size_t __internal_path_length(Node * p, const size_t & level)
00883 {
00884   if (p == Node::NullPtr) 
00885     return 0;
00886 
00887   return level + __internal_path_length(LLINK(p), level + 1) +
00888          __internal_path_length(RLINK(p), level + 1);
00889 }
00897     template <class Node> inline 
00898 size_t internal_path_length(Node * p) 
00899 {
00900   return __internal_path_length(p, 0);
00901 }
00914     template <class Node, class Compare> inline
00915 bool check_binary_search_tree(Node * node)
00916 {
00917   if (node == Node::NullPtr) 
00918     return true;
00919 
00920   if (LLINK(node) != Node::NullPtr)
00921     {
00922       if (Compare () (KEY(LLINK(node)), KEY(node)))
00923         return check_binary_search_tree<Node, Compare>(LLINK(node));
00924       else
00925         return false;
00926     }
00927 
00928   if (RLINK(node) != Node::NullPtr)
00929     {
00930       if (Compare () (KEY(node), KEY(RLINK(node))))
00931         return check_binary_search_tree<Node, Compare>(RLINK(node));
00932       else
00933         return false;
00934     }
00935 
00936   return true;
00937 }
00938 
00939     template <class Node> inline
00940 bool check_binary_search_tree(Node * node)
00941 {
00942   return 
00943     check_binary_search_tree<Node, Aleph::less<typename Node::key_type> >(node);
00944 }
00959     template <class Node> inline
00960   Node * 
00961 preorder_to_binary_search_tree(DynArray<typename Node::key_type> & preorder, 
00962                                const int & l, const int & r)
00963 {
00964   if (l > r)
00965     return Node::NullPtr;
00966 
00967   Node * root = new Node(preorder[l]);
00968 
00969   if (l == r)
00970     return root;
00971 
00972   int first_greater = l + 1;
00973 
00974   while ( (first_greater <= r) and (preorder[first_greater] < preorder[l]))
00975     ++first_greater; 
00976   LLINK(root) = 
00977     preorder_to_binary_search_tree<Node>(preorder, l + 1, first_greater - 1);
00978   RLINK(root) = 
00979     preorder_to_binary_search_tree<Node>(preorder, first_greater, r);
00980 
00981   return root;
00982 }
01000     template <class Node, class Compare> inline 
01001 Node * searchInBinTree(Node * root, const typename Node::key_type & key)
01002 {
01003   Node * p = root;
01004 
01005   while (p != Node::NullPtr)
01006     if (Compare () (key, KEY(p)))       // ¿Está en rama izquierda?
01007       p = static_cast<Node*>(LLINK(p)); // baje a rama izquierda
01008     else if (Compare() (KEY(p), key))   // ¿Está en rama derecha?
01009       p = static_cast<Node*>(RLINK(p)); // baje a rama derecha
01010     else
01011       break; // se encontró!
01012 
01013   return p;
01014 }
01015     template <class Node> inline
01016 Node * searchInBinTree(Node *root, const typename Node::key_type & key)
01017 {
01018   return 
01019     searchInBinTree<Node, Aleph::less<typename Node::key_type> >(root, key);
01020 }
01032     template <class Node>
01033 Node * find_min(Node * root)
01034 {
01035   Node * ret_val = root;
01036   while (LLINK(ret_val) != Node::NullPtr)
01037     ret_val = static_cast<Node*>(LLINK(ret_val));
01038 
01039   return ret_val;
01040 }
01041 
01053     template <class Node>
01054 Node * find_max(Node * root)
01055 {
01056   Node * ret_val = root;
01057   while (RLINK(ret_val) != Node::NullPtr)
01058     ret_val = static_cast<Node*>(RLINK(ret_val));
01059 
01060   return ret_val;
01061 }
01074     template <class Node> inline
01075 Node * find_successor(Node*  p, Node *& pp)
01076 { 
01077 
01078   I(p != Node::NullPtr);
01079   I(RLINK(p) != Node::NullPtr);
01080 
01081   pp = p;
01082   p  = static_cast<Node*>(RLINK(p));
01083 
01084   while (LLINK(p) != Node::NullPtr)
01085     {
01086       pp = p;
01087       p  = static_cast<Node*>(LLINK(p));
01088     }
01089 
01090   return p;
01091 }
01104     template <class Node> inline
01105 Node* find_predecessor(Node * p, Node *& pp)
01106 {
01107   I(p != Node::NullPtr);
01108   I(LLINK(pp) != Node::NullPtr);
01109 
01110   pp = p;
01111   p  = static_cast<Node*>(LLINK(p));
01112 
01113   while (RLINK(p) != Node::NullPtr)
01114     {
01115       pp = p;
01116       p  = static_cast<Node*>(RLINK(p));
01117     }
01118 
01119   return p;
01120 }
01143     template <class Node, class Compare> inline
01144 Node * search_parent(Node *                          root, 
01145                      const typename Node::key_type & key, 
01146                      Node *&                         parent)
01147 {
01148 
01149   I((LLINK(parent) == root) or (RLINK(parent) == root));
01150   I(root != Node::NullPtr);
01151 
01152   Compare cmp;
01153   Node * p = root;
01154 
01155   while (true)
01156     if (cmp(key, KEY(p)))
01157       { 
01158         if (LLINK(p) == Node::NullPtr)
01159           return p;
01160 
01161         parent = p;
01162         p = static_cast<Node*>(LLINK(p));
01163       }
01164     else if (cmp(KEY(p), key))
01165       {
01166         if (RLINK(p) == Node::NullPtr)
01167           return p;
01168 
01169         parent = p;
01170         p = static_cast<Node*>(RLINK(p));
01171       }
01172     else
01173       return p;
01174 }
01175     template <class Node> inline
01176 Node * search_parent(Node * root, const typename Node::key_type & key, 
01177                      Node *& parent)
01178 {
01179   return search_parent<Node, Aleph::less<typename Node::key_type> >
01180     (root, key, parent);
01181 }
01199     template <class Node, class Compare> inline
01200 Node * search_rank_parent(Node * root, const typename Node::key_type & key)
01201 {
01202 
01203   I(root != Node::NullPtr);
01204 
01205   Compare cmp;
01206   Node *p = root;
01207 
01208   while (true)
01209     if (cmp(key, KEY(p)))
01210       { 
01211         if (LLINK(p) == Node::NullPtr)
01212           return p;
01213         
01214         p = static_cast<Node*>(LLINK(p));
01215       }
01216     else if (cmp(KEY(p), key))
01217       {
01218         if (RLINK(p) == Node::NullPtr)
01219           return p;
01220 
01221         p = static_cast<Node*>(RLINK(p));
01222       }
01223     else
01224       return p;
01225 }
01226     template <class Node> inline
01227 Node * search_rank_parent(Node * root, const typename Node::key_type & key)
01228 {
01229   return 
01230     search_rank_parent<Node, Aleph::less<typename Node::key_type> >(root, key);
01231 }
01250     template <class Node, class Compare> inline
01251 Node * insert_in_binary_search_tree(Node *& root, Node * p)
01252 {
01253   if (root == Node::NullPtr) // ¿Inserción en árbol vacío?
01254     return root = p;
01255 
01256   if (Compare () (KEY(p), KEY(root)))      // ¿p < root?
01257         // insertar en subárbol izquierdo
01258     return insert_in_binary_search_tree <Node, Compare> 
01259       (static_cast<Node*&>(LLINK(root)), p);
01260   else if (Compare () (KEY(root), KEY(p))) // ¿p > root?
01261         // insertar en subárbol derecho
01262     return insert_in_binary_search_tree <Node, Compare> 
01263       (static_cast<Node*&>(RLINK(root)), p);
01264 
01265   return Node::NullPtr; // clave repetida ==> no hay inserción
01266 }
01267 
01268     template <class Node> inline
01269 Node * insert_in_binary_search_tree(Node *& root, Node * p)
01270 {
01271   return
01272     insert_in_binary_search_tree<Node, Aleph::less<typename Node::key_type> >
01273       (root, p);
01274 }
01275 # define SPLIT split_key_rec<Node, Compare>
01276 
01296     template <class Node, class Compare> inline
01297 bool split_key_rec(Node * root, 
01298                    const typename Node::key_type & key, 
01299                    Node *& ts, Node *& tg)
01300 {
01301   if (root == Node::NullPtr)
01302     {    // key no se encuentra en árbol ==> split tendrá éxito
01303       ts = tg = Node::NullPtr;
01304       return true;
01305     }
01306   if ( Compare() (key, KEY(root)) ) // ¿key < KEY(root)?
01307     {
01308       if (SPLIT(static_cast<Node*&>(LLINK(root)), key, 
01309                 ts, static_cast<Node*&>(LLINK(root))))
01310         {
01311           tg = root;
01312           return true;
01313         }
01314       else
01315         return false;
01316     }
01317   if ( Compare() (KEY(root), key) ) // ¿key > KEY(root)?
01318     {
01319       if (SPLIT(static_cast<Node*&>(RLINK(root)), key, 
01320                 static_cast<Node*&>(RLINK(root)), tg))
01321         {
01322           ts = root;
01323           return true;
01324         }
01325       else
01326         return false;
01327     }
01328   return false; // clave existe en árbol ==> se deja intacto
01329 }
01330 
01331 # undef SPLIT
01332 
01333     template <class Node> inline
01334 bool split_key_rec(Node * root, const typename Node::key_type & key, 
01335                    Node *& l, Node *& r)
01336 {
01337   return split_key_rec<Node, Aleph::less<typename Node::key_type> >(root, 
01338                                                                     key, l, r);
01339 }
01355     template <class Node> inline
01356 Node * join_exclusive(Node *& ts, Node *& tg)
01357 {
01358   if (ts == Node::NullPtr)
01359     return tg;
01360 
01361   if (tg == Node::NullPtr)
01362     return ts;
01363 
01364   LLINK(tg) = join_exclusive(RLINK(ts), LLINK(tg));
01365 
01366   RLINK(ts) = tg;
01367 
01368   Node * ret_val = ts;
01369 
01370   ts = tg = Node::NullPtr; // deben quedar vacíos después del join
01371 
01372   return ret_val;
01373 }  
01374 # define REMOVE remove_from_search_binary_tree<Node, Compare>
01375 
01393     template <class Node, class Compare> inline
01394 Node * remove_from_search_binary_tree(Node *& root, 
01395                                       const typename Node::key_type & key)
01396 {
01397   if (root == Node::NullPtr)
01398     return Node::NullPtr;
01399 
01400   if (Compare () (key, KEY(root)))
01401     return REMOVE(static_cast<Node*&>(LLINK(root)), key);
01402   else if (Compare () (KEY(root), key))
01403     return REMOVE(static_cast<Node*&>(RLINK(root)), key);
01404   
01405   Node * ret_val = root; // respaldar root que se va a borrar
01406 
01407   root = join_exclusive(static_cast<Node*&>(LLINK(root)),
01408                         static_cast<Node*&>(RLINK(root)));
01409 
01410   ret_val->reset();
01411 
01412   return ret_val;
01413 }
01414 # undef REMOVE
01415 # define REMOVE remove_from_search_binary_tree<Node,\
01416           Aleph::less<typename Node::key_type> >
01417 
01418     template <class Node> inline
01419 Node * remove_from_search_binary_tree(Node *& root, 
01420                                       const typename Node::key_type & key)
01421 {
01422   return REMOVE(root, key);
01423 }
01424 
01425 # undef REMOVE
01426 
01446   template <class Node, class Compare> inline
01447 Node * insert_root(Node *& root, Node * p)
01448 {
01449   Node * l = Node::NullPtr, 
01450        * r = Node::NullPtr; // para guardar resultados del split
01451 
01452   if (not split_key_rec<Node, Compare>(root, KEY(p), l, r))
01453     return Node::NullPtr; 
01454 
01455   LLINK(p) = l;
01456   RLINK(p) = r;
01457 
01458   root = p;
01459 
01460   return root; 
01461 }
01462     template <class Node> inline
01463 Node * insert_root(Node *& root, Node * p)
01464 {
01465   return insert_root<Node, Aleph::less<typename Node::key_type> >(root, p);
01466 }
01485     template <class Node, class Compare> inline
01486 Node * join_preorder(Node * t1, Node * t2, Node *& dup)
01487 {
01488   if (t2 == Node::NullPtr)
01489     return t1;
01490 
01491   Node * l = static_cast<Node*>(LLINK(t2)); // respaldos de ramas de t2
01492   Node * r = static_cast<Node*>(RLINK(t2));
01493 
01494   if (insert_in_binary_search_tree <Node, Compare> (t1, t2) == Node::NullPtr)
01495         // inserción fallida ==> elemento duplicado ==> insertar en dup
01496     insert_in_binary_search_tree<Node, Compare>(dup, t2);
01497 
01498   join_preorder(t1, l, dup);
01499   join_preorder(t1, r, dup);
01500 
01501   return t1;
01502 }
01520     template <class Node, class Compare> inline
01521 Node * join(Node * t1, Node * t2, Node *& dup)
01522 {
01523   if (t1 == Node::NullPtr)
01524     return t2;
01525 
01526   if (t2 == Node::NullPtr)
01527     return t1;
01528 
01529   Node * l = static_cast<Node*>(LLINK(t1)); // respaldos de ramas de t1
01530   Node * r = static_cast<Node*>(RLINK(t1));
01531 
01532   t1->reset();
01533 
01534   if (insert_root<Node, Compare>(t2, t1) == Node::NullPtr)
01535     insert_in_binary_search_tree<Node, Compare>(dup, t1); 
01536 
01537   LLINK(t2) = join<Node, Compare>(l, static_cast<Node*>(LLINK(t2)), dup);
01538   RLINK(t2) = join<Node, Compare>(r, static_cast<Node*>(RLINK(t2)), dup);
01539 
01540   return t2;
01541 }
01542 
01543     template <class Node> inline
01544 Node * join(Node * t1, Node * t2, Node *& dup)
01545 {
01546   return join<Node, Aleph::less<typename Node::key_type> >(t1, t2, dup);
01547 }
01548 
01553     template <class Node> inline
01554 Node * rotate_to_right(Node * p)
01555 {
01556 
01557   I(p != Node::NullPtr);
01558 
01559   Node * q  = static_cast<Node*>(LLINK(p));
01560   LLINK(p) = RLINK(q);
01561   RLINK(q) = p;
01562 
01563   return q;           
01564 } 
01577     template <class Node> inline
01578 Node * rotate_to_right(Node * p, Node * pp)
01579 {
01580 
01581   I(p != Node::NullPtr);
01582   I(pp != Node::NullPtr);
01583   I((static_cast<Node*>(LLINK(pp)) == p) or 
01584          (static_cast<Node*>(RLINK(pp)) == p));
01585 
01586   Node *q = static_cast<Node*>(LLINK(p));
01587         
01588   LLINK(p) = RLINK(q);
01589   RLINK(q) = p;
01590 
01591   if (static_cast<Node*>(LLINK(pp)) == p) // actualización del padre
01592     LLINK(pp) = q;
01593   else
01594     RLINK(pp) = q;
01595      
01596   return q;           
01597 } 
01602     template <class Node> inline
01603 Node* rotate_to_left(Node * p)
01604 {
01605   I(p != Node::NullPtr);
01606 
01607   Node *q  = static_cast<Node*>(RLINK(p));
01608   RLINK(p) = LLINK(q);
01609   LLINK(q) = p;
01610 
01611   return q;                  
01612 } 
01613 
01628     template <class Node> inline
01629 Node* rotate_to_left(Node * p, Node * pp)
01630 {
01631   I(p != Node::NullPtr);
01632   I(pp != Node::NullPtr);
01633   I(static_cast<Node*>(LLINK(pp)) == p or 
01634          static_cast<Node*>(RLINK(pp)) == p);
01635 
01636   Node *q = static_cast<Node*>(RLINK(p));
01637 
01638   RLINK(p) = LLINK(q);
01639   LLINK(q) = p;
01640 
01641       // actualización del padre
01642   if (LLINK(pp) == p)
01643     LLINK(pp) = q;
01644   else
01645     RLINK(pp) = q;        
01646       
01647   return q;                  
01648 } 
01673     template <class Node, class Key, class Compare> inline
01674 void split_key(Node * root, const Key & key, Node *& l, Node *& r)
01675 {
01676   if (root == Node::NullPtr) 
01677     {
01678       l = r = (Node*) Node::NullPtr;
01679       return;
01680     }
01681 
01682   Node * current;
01683   Node ** current_parent = NULL;
01684   Node ** pending_child  = NULL;
01685   char current_is_right;
01686   Compare cmp;
01687 
01688   if (cmp (key, KEY(root)))
01689     {
01690       r = root;
01691       pending_child    = &l;
01692       current_is_right = true;
01693     }
01694   else
01695     {
01696       l = root;
01697       pending_child    = &r;
01698       current_is_right = false;
01699     }
01700   current = root;
01701 
01702   while (current != Node::NullPtr) 
01703     {
01704       if (cmp (key, KEY(current)))
01705         { /* current must be in right side */
01706           if (not current_is_right)
01707             { 
01708               current_is_right = not current_is_right;
01709               *pending_child   = *current_parent; /* change of side */
01710               pending_child    = current_parent;
01711             }
01712           current_parent = static_cast<Node**>(&LLINK(current));
01713         }
01714       else
01715         { /* current must be in left side */
01716           if (current_is_right)
01717             { 
01718               current_is_right = not current_is_right;
01719               *pending_child   = *current_parent; /* change of side */
01720               pending_child    = current_parent;
01721             }
01722           current_parent = static_cast<Node**>(&RLINK(current));
01723         }
01724       current = *current_parent;
01725     }
01726   *pending_child = static_cast<Node*>(Node::NullPtr);
01727 }
01728 
01729   template <class Node, class Key> inline
01730 void split_key(Node *root, const Key& key, Node *& l, Node *& r)
01731 {
01732   split_key<Node, Key, Aleph::less<Key> >(root, key, l, r);
01733 }
01734 
01752     template <class Node> inline
01753 void swap_node_with_successor(Node *  p,  // Node for swapping
01754                               Node *& pp, // parent of p
01755                               Node *  q,  // Successor inorder of p 
01756                               Node *& pq) // parent of q
01757  
01758 {
01759   I(p != Node::NullPtr and q != Node::NullPtr and 
01760     pp != Node::NullPtr and pq != Node::NullPtr);
01761   I(LLINK(pp) == p or RLINK(pp) == p); 
01762   I(LLINK(pq) == q or RLINK(pq) == q); 
01763   I(LLINK(q) == Node::NullPtr);        
01764      
01765   /* Set of pp to its new son q */ 
01766   if (LLINK(pp) == p)
01767     LLINK(pp) = q;
01768   else
01769     RLINK(pp) = q;
01770      
01771   LLINK(q) = LLINK(p);
01772   LLINK(p) = Node::NullPtr; 
01773 
01774   /* Checks if successor is right child of p. In this case, p will
01775      become q's son. This situation happens when p's son does not have
01776      a left branch */   
01777   if (RLINK(p) == q) 
01778     {
01779       RLINK(p) = RLINK(q);
01780       RLINK(q) = p;
01781       pq        = pp;
01782       pp        = q;
01783       return;
01784     }
01785 
01786   /* In this case, successor is the leftmost node descending from
01787      right son of p */ 
01788   Node *qr   = RLINK(q); 
01789   RLINK(q)  = RLINK(p);
01790   LLINK(pq) = p;
01791   RLINK(p)  = qr;
01792 
01793   Aleph::swap(pp, pq);
01794 }
01795 
01813     template <class Node> inline
01814 void swap_node_with_predecessor(Node *  p,  // Node for swapping
01815                                 Node *& pp, // p's parent
01816                                 Node *  q,  // Predecessor inorder of p 
01817                                 Node *& pq) // q's parent
01818 {
01819   I((p != Node::NullPtr) and (q != Node::NullPtr) and 
01820     (pp != Node::NullPtr) and (pq != Node::NullPtr));
01821   I((RLINK(pp) == p) or (LLINK(pp) == p)); /* assert pp is parent of p */
01822   I((RLINK(pq) == q) or (LLINK(pq) == q)); /* assert pq is parent of q */
01823   I(RLINK(q) == Node::NullPtr);
01824      
01825   /* Set of pp to its new son q */ 
01826   if (RLINK(pp) == p)
01827     RLINK(pp) = q;
01828   else
01829     LLINK(pp) = q;
01830      
01831   RLINK(q) = RLINK(p);
01832   RLINK(p) = Node::NullPtr; 
01833 
01834   /* Checks if predecessor is left child of p. In this case, p will
01835      become q's son. This situation happens when p's son does not have
01836      a right branch */   
01837   if (LLINK(p) == q) 
01838     {
01839       LLINK(p) = LLINK(q);
01840       LLINK(q) = p;
01841       pq       = pp;
01842       pp       = q;
01843       return;
01844     }
01845 
01846   /* In this case, predecessor is the rightmost node descending from
01847      right son of p */ 
01848   Node *ql  = LLINK(q); 
01849   LLINK(q)  = LLINK(p);
01850   RLINK(pq) = p;
01851   LLINK(p)  = ql;
01852 
01853   Aleph::swap(pp, pq);
01854 }
01855 
01874     template <class Node, class Key, class Compare> inline
01875 Node * insert_root_rec(Node * root, Node * p)
01876 {
01877   if (root == Node::NullPtr)
01878     return p; /* insertion in empty tree */
01879 
01880   if (Compare () (KEY(p), KEY(root)))
01881     { /* insert in left subtree */
01882       Node *left_branch = 
01883         insert_root_rec<Node, Key, Compare>(static_cast<Node*>(LLINK(root)),
01884                                              p);
01885       if (left_branch == Node::NullPtr)
01886         return (Node*) Node::NullPtr;
01887 
01888       LLINK(root) = left_branch;
01889       root        = rotate_to_right(root);
01890     }
01891   else if (Compare () (KEY(root), KEY(p) ))
01892     { /* insert in right subtree */
01893       Node *right_branch = 
01894         insert_root_rec<Node, Key, Compare>(static_cast<Node*>(RLINK(root)), 
01895                                             p);
01896       if (right_branch == Node::NullPtr)
01897         return (Node*) Node::NullPtr;
01898 
01899       RLINK(root) = right_branch;
01900       root        = rotate_to_left(root);
01901     }
01902   else
01903     return (Node*) Node::NullPtr; /* duplicated key */
01904 
01905   return root;
01906 }
01907 
01908     template <class Node, class Key> inline
01909 Node * insert_root_rec(Node * root, Node * p)
01910 {
01911   return insert_root_rec<Node, Key, Aleph::less<Key> >(root, p);
01912 }
01913 
01914 
01915 } // end Aleph
01916 
01917 # endif // TPL_BINNODEUTILS_H 
01918 

Leandro R. León