tpl_tree_node.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_TREE_H
00045 # define TPL_TREE_H
00046 
00047 # include <stdexcept>
00048 # include <dlink.H>
00049 # include <ahFunction.H>
00050 # include <tpl_binNode.H>
00051 
00052 # define ISROOT(p)      ((p)->is_root())
00053 # define ISLEAF(p)      ((p)->is_leaf()) 
00054 # define ISLEFTMOST(p)  ((p)->is_leftmost())
00055 # define ISRIGHTMOST(p) ((p)->is_rightmost())
00056 
00057 # define SIBLING_LIST(p) ((p)->get_sibling_list())
00058 # define CHILD_LIST(p)   ((p)->get_child_list())
00059 # define LCHILD(p)       ((p)->get_left_child())
00060 # define RSIBLING(p)     ((p)->get_right_sibling())
00061 
00062 namespace Aleph
00063 {
00064 
00074     template <class T>
00075 class Tree_Node 
00076 {
00077   T data;
00078   Dlink child;
00079   Dlink sibling;
00080   struct Flags
00081   {
00082     unsigned int is_root          : 1;
00083     unsigned int is_leaf          : 1;
00084     unsigned int is_leftmost      : 1;
00085     unsigned int is_rightmost     : 1;
00086 
00087     Flags() : is_root(1), is_leaf(1), is_leftmost(1), is_rightmost(1)
00088     {
00089       /* empty */
00090     }
00091   };
00092 
00093   Flags flags;
00094   LINKNAME_TO_TYPE(Tree_Node, child);
00095   LINKNAME_TO_TYPE(Tree_Node, sibling);
00096   Tree_Node * upper_link() { return child_to_Tree_Node(child.get_prev()); }
00097 
00098   Tree_Node * lower_link() { return child_to_Tree_Node(child.get_next()); }
00099 
00100   Tree_Node * left_link() { return sibling_to_Tree_Node(sibling.get_prev()); }
00101 
00102   Tree_Node * right_link() { return sibling_to_Tree_Node(sibling.get_next()); }
00103 
00104 public:
00105 
00107   T & get_key() { return get_data(); }
00108 
00110   T & get_data() { return data; }
00111 
00113   typedef T key_type;
00114   Dlink * get_child_list() { return &child; }
00115 
00116   Dlink * get_sibling_list() { return &sibling; }
00118   bool is_root() const { return flags.is_root; }
00119 
00121   bool is_leaf() const { return flags.is_leaf; }
00122 
00124   bool is_leftmost() const { return flags.is_leftmost; }
00125 
00127   bool is_rightmost() const { return flags.is_rightmost; }
00128 
00129   void set_is_root(const bool & value) { flags.is_root = value; }
00130 
00131   void set_is_leaf(const bool & value) { flags.is_leaf = value; }
00132 
00133   void set_is_leftmost(const bool & value) { flags.is_leftmost = value; }
00134 
00135   void set_is_rightmost(const bool & value) { flags.is_rightmost = value; }
00136 
00138   Tree_Node() { /* empty */ }
00139 
00141   Tree_Node(const T & __data) : data(__data) { /* empty */ }
00143   Tree_Node * get_left_sibling() 
00144   {
00145     if (is_leftmost())
00146       return NULL;
00147 
00148     return left_link();
00149   }
00150 
00152   Tree_Node * get_right_sibling()
00153   {
00154     if (is_rightmost())
00155       return NULL;
00156     
00157     return right_link();
00158   }
00160   Tree_Node * get_left_child() 
00161   {
00162     if (is_leaf())
00163       return NULL;
00164 
00165     return lower_link();
00166   }
00167 
00169   Tree_Node * get_right_child()
00170   {
00171     if (is_leaf())
00172       return NULL;
00173 
00174     Tree_Node * left_child = lower_link();
00175 
00176 
00177     I(ISLEFTMOST(left_child));
00178 
00179     return left_child->left_link();
00180   }
00188   Tree_Node * get_child(const int & i) 
00189   {
00190     Tree_Node * c = get_left_child();
00191 
00192     for (int j = 1; c != NULL and j < i; ++j)
00193       c = c->get_right_sibling();
00194 
00195     return c;
00196   }
00198   Tree_Node * get_parent()  
00199   {
00200     if (is_root())
00201       return NULL; 
00202 
00203     Tree_Node * p = this;
00204     while (not ISLEFTMOST(p)) // retroceda hasta ser el nodo más a la izquierda
00205       p = p->left_link();
00206 
00207 
00208     I(not ISROOT(p));
00209     I(not CHILD_LIST(p)->is_empty()); 
00210 
00211     return p->upper_link();
00212   }
00219   void insert_right_sibling(Tree_Node * p)
00220   {
00221     if (p == NULL)
00222       return;
00223 
00224 
00225     I(CHILD_LIST(p)->is_empty());
00226     I(SIBLING_LIST(p)->is_empty());
00227     I(p->is_rightmost() and p->is_leftmost() and p->is_root() and p->is_leaf());
00228 
00229     if (not is_root())
00230       p->set_is_root(false);
00231 
00232     p->set_is_leftmost(false);
00233     
00234     Tree_Node * old_next_node = get_right_sibling(); 
00235 
00236     if (old_next_node != NULL)
00237 
00238       {
00239         I(not this->is_rightmost());
00240 
00241       p->set_is_rightmost(false);
00242 
00243       }
00244 
00245 
00246     this->set_is_rightmost(false);
00247     this->sibling.insert(SIBLING_LIST(p));
00248   }
00255   void insert_left_sibling(Tree_Node * p)
00256   {
00257     if (p == NULL)
00258       return;
00259 
00260 
00261     I(CHILD_LIST(p)->is_empty());
00262     I(SIBLING_LIST(p)->is_empty());
00263     I(p->is_rightmost() and p->is_leftmost() and p->is_root() and p->is_leaf());
00264 
00265     if (not this->is_root()) 
00266       p->set_is_root(false);
00267 
00268     p->set_is_rightmost(false);
00269 
00270     Tree_Node * old_next_node = this->get_left_sibling();
00271 
00272     if (old_next_node != NULL) 
00273 
00274       {
00275         I(not this->is_leftmost());
00276 
00277       p->set_is_leftmost(false);
00278 
00279       }
00280 
00281     else if (not this->child.is_empty()) // verifique si p devendrá en más a
00282                                          // la izquierda 
00283       {     // this es el más a la izquierda ==> p pasará a ser el primogénito
00284 
00285         I(this->is_leftmost());
00286 
00287         Tree_Node * parent = this->get_parent();
00288         Tree_Node * left_child = this->get_left_child();
00289 
00290 
00291         I(parent != NULL or left_child != NULL);
00292 
00293         CHILD_LIST(this)->del(); // sacar this de lista de hijos
00294 
00295             // ahora meter a p en la lista de hijos
00296         if (parent != NULL)
00297           parent->insert(p);
00298         else
00299           left_child->append(p);  
00300       }
00301       
00302     this->set_is_leftmost(false);  
00303     this->sibling.append(SIBLING_LIST(p));
00304   }
00311   void insert_leftmost_child(Tree_Node * p)
00312   {
00313     if (p == NULL)
00314       return;
00315 
00316 
00317     I(CHILD_LIST(p)->is_empty());
00318     I(SIBLING_LIST(p)->is_empty());
00319     I(p->is_rightmost() and p->is_leftmost() and p->is_root() and p->is_leaf());
00320 
00321     p->set_is_root(false);
00322 
00323     if (this->is_leaf())
00324       {
00325         this->set_is_leaf(false);
00326         CHILD_LIST(this)->insert(CHILD_LIST(p));
00327       } 
00328     else
00329       {
00330         Tree_Node * old_left_child_node = this->lower_link();
00331           
00332         old_left_child_node->set_is_leftmost(false);
00333         p->set_is_rightmost(false);
00334         CHILD_LIST(old_left_child_node)->del();
00335         CHILD_LIST(this)->insert(CHILD_LIST(p));
00336 
00337         SIBLING_LIST(old_left_child_node)->append(SIBLING_LIST(p));
00338       }
00339   }
00340 
00347   void insert_rightmost_child(Tree_Node * p)
00348   {
00349     if (p == NULL)
00350       return;
00351 
00352 
00353     I(CHILD_LIST(p)->is_empty());
00354     I(SIBLING_LIST(p)->is_empty());
00355     I(p->is_rightmost() and p->is_leftmost() and p->is_root() and p->is_leaf());
00356 
00357     p->set_is_root(false);
00358 
00359     if (this->is_leaf())
00360       {
00361         this->set_is_leaf(false);
00362         CHILD_LIST(this)->insert(CHILD_LIST(p));
00363       } 
00364     else
00365       {
00366         Tree_Node * old_right_child_node = this->lower_link()->left_link();
00367           
00368         old_right_child_node->set_is_rightmost(false);
00369         p->set_is_leftmost(false);
00370           
00371         SIBLING_LIST(old_right_child_node)->insert(SIBLING_LIST(p));
00372       }
00373   }
00382   void insert_tree_to_right(Tree_Node * tree)
00383   {
00384 
00385     if (tree == NULL)
00386       return;
00387 
00388     if (not this->is_root()) 
00389       throw std::domain_error("\"this\" is not root");
00390 
00391     tree->set_is_leftmost(false);
00392 
00393     Tree_Node * old_next_tree = this->get_right_tree(); 
00394     if (old_next_tree != NULL) 
00395 
00396       {
00397         I(not this->is_rightmost());
00398 
00399         tree->set_is_rightmost(false);
00400 
00401       }
00402 
00403 
00404     this->set_is_rightmost(false);  
00405     SIBLING_LIST(this)->insert(SIBLING_LIST(tree));
00406   }
00408   Tree_Node * get_left_tree() 
00409   {
00410     if (is_leftmost())
00411       return NULL;
00412 
00413 
00414     I(not is_leftmost()); 
00415 
00416     return left_link();
00417   }
00418 
00420   Tree_Node * get_right_tree() 
00421   {
00422     if (is_rightmost())
00423       return NULL;
00424 
00425 
00426     I(not is_rightmost());
00427 
00428     return right_link();
00429   }
00433   Tree_Node * get_last_tree() 
00434   {
00435 
00436     if (not is_leftmost())
00437       throw 
00438         std::range_error("\"this\" is not the leftmost tree in the forest");
00439 
00440     return left_link();
00441   }
00442 };
00443 
00444     template <class Node> static inline
00445 void __tree_preorder_traversal(Node * root, const int & level, 
00446                                const int & child_index,
00447                                void (*visitFct)(Node *, int, int))
00448 {
00449   (*visitFct)(root, level, child_index);
00450 
00451   Node * child = root->get_left_child(); 
00452   for (int i = 0; child != NULL; 
00453        i++, child = child->get_right_sibling())
00454     __tree_preorder_traversal(child, level + 1, i, visitFct);
00455 }
00478     template <class Node> inline
00479 void tree_preorder_traversal(Node * root, void (*visitFct)(Node *, int, int))
00480 {
00481 
00482   if (not root->is_root())
00483     throw std::domain_error("root is not root");
00484 
00485   __tree_preorder_traversal(root, 0, 0, visitFct);
00486 }
00487 
00510     template <class Node> inline
00511 void forest_preorder_traversal(Node * root, 
00512                                void (*visitFct)(Node *, int, int))
00513 {
00514 
00515   if (not root->is_root())
00516     throw std::domain_error("root is not root");
00517 
00518   for (/* nada */; root != NULL; root = root->get_right_tree())
00519 
00520     {
00521       I(root->is_root());
00522 
00523     __tree_preorder_traversal(root, 0, 0, visitFct);
00524 
00525     }
00526 
00527 }
00528     template <class Node> static inline
00529 void __tree_postorder_traversal(Node * node, const int & level, 
00530                                 const int & child_index,
00531                                 void (*visitFct)(Node *, int, int))
00532 {
00533   Node * child = node->get_left_child();
00534   for (int i = 0; child not_eq NULL; i++, child = child->get_right_sibling())
00535     __tree_postorder_traversal(child, level + 1, i, visitFct);
00536 
00537   (*visitFct)(node, level, child_index);
00538 }
00539 
00561     template <class Node> inline
00562 void tree_postorder_traversal(Node * root, 
00563                               void (*visitFct)(Node *, int, int))
00564 {
00565   __tree_postorder_traversal(root, 0, 0, visitFct);
00566 }
00567 
00591     template <class Node> inline
00592 void forest_postorder_traversal(Node * root, 
00593                                 void (*visitFct)(Node *, int, int))
00594 {
00595 
00596   if (not root->is_leftmost())
00597     throw std::domain_error("root is not the leftmost node of forest");
00598 
00599   if (not root->is_root())
00600     throw std::domain_error("root is not root");
00601 
00602   for (/* nada */; root not_eq NULL; root = root->get_right_sibling())
00603 
00604     {
00605       I(root->is_root());
00606 
00607     __tree_postorder_traversal(root, 0, 0, visitFct);
00608 
00609     }
00610 
00611 }
00620     template <class Node> inline  
00621 void destroy_tree(Node * root)
00622 {
00623       // recorrer los subárboles de derecha a izquierda
00624   for (Node * p = root->get_right_child(); p != NULL; /* nada */)
00625     {
00626       Node * to_delete = p;      // respaldar subárbol a borrar p
00627       p = p->get_left_sibling(); // Avanzar p a hermano izquierdo
00628       SIBLING_LIST(to_delete)->del(); // eliminar to_delete de lista hermanos
00629       destroy_tree(to_delete);   // eliminar recursivamente árbol
00630     }
00631 
00632       // Si to_delete es el más a la izquierda ==> sacarlo de lista de hijos
00633   if (root->is_leftmost()) 
00634     CHILD_LIST(root)->del(); 
00635 
00636   delete root;
00637 }
00638 
00651     template <class Node> inline 
00652 void destroy_forest(Node * root)
00653 {
00654 
00655   if (not root->is_leftmost())
00656     throw std::domain_error("root is not the leftmost tree of forest");
00657 
00658   if (not root->is_root())
00659     throw std::domain_error("root is not root");
00660 
00661       // recorre los árboles de izquierda a derecha
00662   while (root != NULL) 
00663     {
00664       Node * to_delete = root; // respalda raíz 
00665 
00666       root = root->get_right_sibling(); // avanza a siguiente árbol 
00667 
00668       SIBLING_LIST(to_delete)->del(); // elimine árbol de lista de árboles
00669 
00670       destroy_tree(to_delete); // Borre el árbol
00671     }
00672 }
00679     template <class Node>
00680 size_t compute_height(Node * root) 
00681 {
00682   size_t max_h = 0;
00683   size_t temp_h;
00684 
00685   for (Node * aux = root->get_left_child(); aux != NULL; 
00686        aux = aux->get_right_sibling()) 
00687     if ((temp_h = compute_height(aux)) > max_h)
00688       max_h = temp_h;
00689 
00690   return max_h + 1;
00691 }
00692     template <class Node> static inline
00693 Node * __deway_search(Node *         node, 
00694                       int            path [], 
00695                       const int &    idx,
00696                       const size_t & size)
00697 {
00698   if (node == NULL)
00699     return NULL;
00700 
00701   if (idx > size)
00702     throw std::out_of_range("index out of maximum range");
00703 
00704 
00705   if (path[idx] < 0) // verifique si se ha alcanzado el nodo
00706     return node; 
00707 
00708       // avance hasta el próximo hijo path[0]
00709   Node * child = node->get_left_child();
00710   for (int i = 0; i < path[idx] and child != NULL; ++i)
00711     child = child->get_right_sibling();
00712 
00713   return __deway_search(child, path, idx + 1, size); // siga en próximo nivel
00714 }
00728     template <class Node> inline
00729 Node * deway_search(Node * root, int path [], const size_t & size)
00730 {
00731   for (int i = 0; root != NULL; i++, root = root->get_right_sibling())
00732     if (path[0] == i)
00733       return __deway_search(root, path, 1, size);
00734 
00735   return NULL;
00736 }
00737     template <class Node, class Equal> inline static
00738 Node * __search_deway(Node *                          root, 
00739                       const typename Node::key_type & key,
00740                       const size_t &                  current_level,
00741                       int                             deway [], 
00742                       const size_t &                  size, 
00743                       size_t &                        n);
00768     template <class Node, class Equal> inline
00769 Node * search_deway(Node *                          root, 
00770                     const typename Node::key_type & key,
00771                     int                             deway [], 
00772                     const size_t &                  size, 
00773                     size_t &                        n)
00774 {
00775   n = 1; // valor inicial de longitud de número de Deway
00776 
00777   if (size < n)
00778     throw std::overflow_error("there is no enough space for deway array");
00779 
00780 
00781       // recorrer los árboles de la arborescencia
00782   for (int i = 0; root != NULL; i++, root = root->get_right_sibling())
00783     {
00784       deway[0] = i;
00785 
00786       Node * result =
00787         __search_deway <Node, Equal> (root, key, 0, deway, size, n);
00788 
00789       if (result != NULL)
00790         return result;
00791     }
00792 
00793   return NULL;
00794 }
00795     template <class Node> inline
00796 Node * search_deway(Node *                          root, 
00797                     const typename Node::key_type & key,
00798                     int                             deway [], 
00799                     const size_t &                  size, 
00800                     size_t &                        n)
00801 {
00802   return search_deway <Node, Aleph::equal_to<typename Node::key_type> >
00803     (root, key, deway, size, n) ; 
00804 }
00805     template <class Node, class Equal> inline static
00806 Node * __search_deway(Node *                          root, 
00807                       const typename Node::key_type & key,
00808                       const size_t &                  current_level,
00809                       int                             deway [], 
00810                       const size_t &                  size, 
00811                       size_t &                        n)
00812 {
00813 
00814   if (current_level >= size) 
00815     throw std::overflow_error("there is no enough space for deway array");
00816 
00817   if (root == NULL)
00818     return NULL;
00819 
00820   if (Equal () (KEY(root), key))
00821     {
00822       n = current_level + 1; // longitud del arreglo deway
00823 
00824       return root;
00825     }
00826 
00827   Node * child = root->get_left_child();
00828   for (int i = 0; child != NULL; i++, child = child->get_right_sibling())
00829     {
00830       deway[current_level + 1] = i;
00831 
00832       Node * result = __search_deway <Node, Equal> 
00833         (child, key, current_level + 1, deway, size, n);
00834 
00835       if (result!= NULL)
00836         return result;
00837     }
00838 
00839   return NULL;
00840 }
00861     template <class TNode, class BNode>
00862 BNode * forest_to_bin(TNode * root)
00863 {
00864   if (root == NULL)
00865     return BNode::NullPtr;
00866   
00867   BNode * result = new BNode (root->get_key());
00868   
00869   LLINK(result) = forest_to_bin<TNode, BNode>(root->get_left_child());
00870   RLINK(result) = forest_to_bin<TNode, BNode>(root->get_right_sibling());
00871   
00872   return result;
00873 }
00874     template <class TNode, class BNode> inline static
00875 void insert_child(BNode * lnode, TNode * tree_node)
00876 {
00877   if (lnode == BNode::NullPtr)
00878     return;
00879   
00880   TNode * child = new TNode(KEY(lnode));
00881   
00882   tree_node->insert_leftmost_child(child);
00883 }
00884     template <class TNode, class BNode> inline static
00885 void insert_sibling(BNode * rnode, TNode * tree_node)
00886 {
00887   if (rnode == BNode::NullPtr)
00888     return;
00889   
00890   TNode * sibling = new TNode(KEY(rnode));
00891   
00892   tree_node->insert_right_sibling(sibling);
00893 }
00894     template <class TNode, class BNode> inline static
00895 void bin_to_tree(BNode * broot, TNode * troot)
00896 {
00897   if (broot == BNode::NullPtr)
00898     return;
00899   
00900   insert_child(LLINK(broot), troot);
00901   TNode * left_child =  troot->get_left_child();
00902   bin_to_tree(LLINK(broot), left_child);
00903   
00904   insert_sibling(RLINK(broot), troot);
00905   TNode * right_sibling = troot->get_right_sibling();
00906   bin_to_tree(RLINK(broot), right_sibling);
00907 }
00927     template <class TNode, class BNode> inline 
00928 TNode * bin_to_forest(BNode * broot) 
00929 {
00930   if (broot == BNode::NullPtr)
00931     return NULL;
00932   
00933   TNode * troot = new TNode (KEY(broot));
00934   
00935   bin_to_tree(broot, troot);
00936 
00937   return troot;
00938 }
00939 
00940 } // fin namespace Aleph
00941 
00942 # endif // TPL_TREE_H
00943 

Leandro R. León