Página principal | Lista de namespace | Lista de componentes | Lista de archivos | Miembros del Namespace  | Miembros de las clases | Archivos de los miembros | Páginas relacionadas

Tree_Ex.h

Ir a la documentación de este archivo.
00001 // Tree_Ex.h (c) 2006 adolfo@di-mare.com
00002 
00003 /** \file Tree_Ex.h
00004     \brief Algunas funciones de ejemplos de uso de la clase \c Tree<E>.
00005  
00006     \author Adolfo Di Mare <adolfo@di-mare.com>
00007     \date   2006
00008 
00009     - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04
00010 */
00011 
00012 #ifndef Tree_Ex_h
00013 #define Tree_Ex_h
00014 
00015 #include "Tree_L.h"
00016 
00017 #include <iostream>
00018 #include <iomanip>
00019 #include <cassert>
00020 #include <string>
00021 
00022 /// Definido por la biblioteca C++ estándar
00023 namespace std {} // Está acá para que Doxygen lo documente
00024 
00025 using namespace std; // cout
00026 
00027 /** Incrementa \c "n" en el número de hijos que tiene el sub-árbol cuya raíz es \c "T".
00028     - Cambia el valor de \c "n"
00029     - No cuenta a la raíz de \c "T"
00030     - Usualmente se invoca así: \code { n = 1; My_Count0(T, n); } \endcode
00031 
00032     \pre <code> ! T. Empty() </code> */
00033 template <class E>
00034 void My_Count0(const Tree<E>& T, unsigned & n) {
00035     for (unsigned i=T.Leftmost_N(); i <= T.Rightmost_N(); ++i) {
00036         if (! T.Child(i).Empty() ) {
00037             ++n; // cuenta a este hijo
00038             My_Count0( T.Child(i), n );
00039         }
00040     }
00041 }
00042 
00043 /// Retorna la cantidad de valores almacenados en el árbol.
00044 template <class E>
00045 unsigned My_Count(const Tree<E>& T) {
00046     if (T.Empty()) {
00047         return 0;
00048     } else {
00049         unsigned n = 1; // comienza contando en uno...
00050         My_Count0(T, n); // ... porque Count0() no cuenta la raíz
00051         return n;
00052     }
00053 }
00054 
00055 /// Retorna la cantidad de hijos de "T".
00056 template <class E>
00057 unsigned Count_Children ( const Tree<E> & T ) {
00058         Tree<E> L_Child = T.Leftmost();
00059     if ( L_Child.Empty() ) {
00060         return 0; // como no hay hijo más izquierdo ==> se terminó el trabajo
00061     }
00062 
00063     unsigned n = 1;
00064     Tree<E> R_Child = T.Rightmost();
00065     Tree<E>&  Child = L_Child;
00066     for (;;) {
00067         if (Child == R_Child) {
00068             break;
00069         } else {
00070             ++n;
00071         }
00072         Child = Child.Right_Sibling();
00073     }
00074     return n;
00075 }
00076 /// Compara recursivamente los árboles \c "p" y \c "q".
00077 template <class E>
00078 bool Comp( const Tree<E>& p, const Tree<E>& q ) {
00079     if ( p.Same(q) ) {
00080         return true;
00081     }
00082     if ( p.Empty() || q.Empty() ) { // son diferentes...
00083         return false; // ...pues sólo 1 está vácio
00084     }
00085     if ( p.Child_Number() != q.Child_Number() ) {
00086         return false; // valor diferente en la raíz
00087     }
00088     if ( ! (p.Data() == q.Data()) ) {
00089         return false; // valor diferente en la raíz
00090     }
00091 
00092     // A comparar a todos los hijos
00093     unsigned rp = p.Rightmost_N(), lp = p.Leftmost_N();
00094     unsigned rq = q.Rightmost_N(), lq = q.Leftmost_N();
00095     if ((lp != lq) || (rp != rq)) {
00096         return false;
00097     }
00098     for (unsigned i=lp; i<=rp ; ++i) {
00099         if (! Comp(p.Child(i), q.Child(i)) ) {
00100             return false;
00101         }
00102     }
00103 
00104     return true; // pues nunca encontró nodos diferentes
00105 }
00106 
00107 /** Graba en \c "cout" el contenido del árbol \c "T".
00108     - Indenta a los hijos \c "indent" espacios dobles
00109     - Numera a los hijos a partir de \c "num" usando 2 dígitos
00110     - Usualmente se invoca así: \c Print(T); */
00111 template <class E>
00112 void Print( const Tree<E>& T, unsigned indent=0, unsigned num=0 ) {
00113     if ( T.Empty() ) {
00114         return;
00115     }
00116 
00117     cout << endl; // indenta doble espacio
00118     for (unsigned i = 0; i < indent; ++i) {
00119         cout << ' ' << ' ';
00120     }
00121 
00122     cout << '[' << setfill('0') << setw(2) << num << "]==> " << *T;
00123 
00124     Tree<E> Child = T.Leftmost();
00125     while ( ! Child.Empty() ) {
00126         Print( Child, indent+1, Child.Child_Number() );
00127         Child = Child.Right_Sibling();
00128     }
00129 }
00130 
00131 /// Cambia las letras de cajita para que el árbol de \c Ztree_Print() se vea bonito en DOS
00132 /// \post No funciona porque Win <==> \c cout convierten a su antojo las letras
00133 string DOS_string(string& s) {
00134 
00135     if      (s == "¦  ") { return "À  "; }
00136     else if (s == "+--") { return "ÃÄÄ"; }
00137     else if (s == "+--") { return "ÀÄÄ"; }
00138     else return s;  // me dio pereza obligarlo a funcionar
00139 }
00140 
00141 /** Graba en \c "cout" el contenido de "T" de la forma en que Ztree.com despliega un árbol.
00142     - "level" indica que el nivel de anidamiento desde la raíz hasta el nodo
00143     - "last_child" indica se éste es el último hijo de su padre
00144     
00145     \remarks Forma usual de invocación: \c Ztree_Print( T );
00146     \code
00147     a
00148     |--b                           a
00149     |  |--f                       /|\
00150     |  |--g                     / / \ \
00151     |  +--h                    b  c d  e
00152     |--c                      /|\     /|\
00153     |--d                     f g h   i j k
00154     +--e                              / \
00155        |--i                           l m
00156        |--j                            / \
00157        |  |--l                         n o
00158        |  +--m
00159        |     |--n
00160        |     +--o
00161        +--k
00162       \endcode
00163 */
00164 template <class E>
00165 void Ztree_Print( const Tree<E> & T, string s="", unsigned level = 0, bool last_child = true) {
00166     if ( T.Empty() ) {
00167         return; // se sale si el árbol está vacío
00168     }
00169 
00170     cout << s << T.Data() << endl;
00171 
00172     Tree<E> L_Child = T.Leftmost();
00173     if ( L_Child.Empty() ) { // Si no hay hijo más izquierdo
00174         return; // ==> no hay hijos ==> se terminó el trabajo
00175     }
00176     if (level > 0) {
00177         if (last_child) {
00178             s.resize ( s.size () - 3 );
00179             s += "   ";
00180         } else {
00181             s.resize ( s.size () - 3 );
00182             s += "|  ";
00183         }
00184     }
00185 
00186     s += "|  ";
00187     Tree<E> R_Child = T.Rightmost();
00188     Tree<E>&  Child = L_Child;
00189     for (;;) {
00190         if (Child == R_Child) { // Al último le hace un quiebre cuadradito
00191             s.resize ( s.size () - 3 );
00192             s += "+--";
00193             Ztree_Print(Child, s, level+1, true);
00194             s.resize ( s.size () - 3 );
00195             s += "   ";
00196             break;
00197         } else {
00198             s.resize ( s.size () - 3 );
00199             s += "|--";
00200             Ztree_Print(Child, s, level+1, false);
00201             s.resize ( s.size () - 3 );
00202             s += "   ";
00203         }
00204         Child = Child.Right_Sibling();
00205     }
00206 }
00207 
00208 /** Convierte a \c "T" en su sub-árbol espejo.
00209     - El sub-árbol es espejo es aquel en el que, recursivamente, los hijos quedan
00210       en orden inverso del orden en el que aparecían originalmente en \c "T".
00211 
00212     \code
00213            a                a
00214           /|\              /|\
00215         / / \ \          / / \ \
00216        b  c d  e        e  d c  b
00217       /|\     /|\      /|\     /|\
00218      f g h   i j k    k j i   h g f
00219               / \      / \
00220               l m      m l
00221                / \    / \
00222                n o    o n
00223     \endcode  */
00224 template <class E>
00225 void Mirror( Tree<E>& T ) {
00226     if ( T.Empty() ) {
00227         return; // se sale si el árbol está vacío
00228     }
00229 
00230     Tree<E> Child = T.Leftmost();
00231     while ( ! Child.Empty() ) { // recursión para cambiar a todos los hijos
00232         Mirror( Child );
00233         Child = Child.Right_Sibling();
00234     }
00235 
00236     unsigned N = T.Rightmost_N();
00237     Tree<E>     Ti, Tn_i;        // [0] [1] [2] [3] [4]    N == 4
00238     unsigned i, Mid = (N+1) / 2; //  i   i < 2 ==  Mid ==> 2 == 4/2 == 5/2
00239     for (i=0; i<Mid; ++i) { // Intercambia los hijos i <==> N - i
00240         #if (0)
00241         { // dice qué hizo
00242             cout << endl; Print(T);
00243             Tree<E> Ti   = T.Child( i );
00244             Tree<E> Tn_i = T.Child( N - i );
00245             cout << endl;
00246             string sTi ="[]"; string sTn_i = "[]";
00247             if (!Ti.Empty()) sTi=*Ti;
00248             if (!Tn_i.Empty()) sTn_i=*Tn_i; unsigned DT = 2+Depth(T);
00249             for (unsigned j=0; j<DT; ++j) { cout << "  "; }
00250                 cout << "[\"" << *T << "\"].Graft(" << i   << ",\"" << sTn_i << "\")" << endl;
00251             for (unsigned j=0; j<DT; ++j) { cout << "  "; }
00252                 cout << "[\"" << *T << "\"].Graft(" << N-i << ",\"" << sTi   << "\")" << endl;
00253         }
00254         #endif
00255         Ti   = T.Child( i );
00256         Tn_i = T.Child( N - i );
00257         T.Graft( i,     Tn_i );     // assert(( Ti.Empty() ? true : Ti.Father().Empty() ));
00258         T.Graft( N - i, Ti   );
00259     }
00260     // cout << "# == " << T.Count() << endl; Print(T);
00261 }
00262 
00263 /// Retorna true si \c "Father" es un ancestro de \c "Child".
00264 /// - La raíz no tiene ancestros.
00265 /// - Un árbol vacío no tiene ancestros.
00266 template <class E>
00267 bool Ancestor( const Tree<E> & Child, const Tree<E> & Father ) {
00268     if ( Child.Empty() ) {
00269         return false;
00270     }
00271     Tree<E> T = Child.Father();
00272     while ( ! T.Empty() ) {
00273         if ( T.Same( Father ) ) { // No es válido usar la comparación profunda por valor
00274             return true;
00275         }
00276         T = T.Father();
00277     }
00278     return false;
00279 }
00280 
00281 /// Retorna true cuando el sub-árbol \c "T" es una hoja,
00282 /// o sea, cuando "T" no tiene hijos.
00283 /// - Un sub-árbol vacío no es una hoja porque no tiene raíz.
00284 template <class E>
00285 inline bool Is_Leaf( const Tree<E> & T ) {
00286     return ( ! T.Empty() && T.Leftmost().Empty() );
00287 } // Is_Leaf()
00288 
00289 /// Retorna true cuando el sub-árbol \c "T" es una raíz,
00290 /// o sea, cuando \c "T" no tiene padre.
00291 /// - Un sub-árbol vacío no es una raíz porque no tiene raíz.
00292 template <class E>
00293 inline bool Is_Root( const Tree<E> & T ) {
00294     return ( !T.Empty() && !T.Father().Empty() );
00295 } // Is_Root()
00296 
00297 /// Calcula la altura de sub-árbol.
00298 ///  - Esta función es el paso recursivo necesario para implementar \c Height()
00299 ///  - Recorre recursivamente el árbol y recuerda la máxima profundidad encontrada en \c "max".
00300 ///  - \c "actual" es la profundidad del nodo actual.
00301 template <class E>
00302 void Height0( const Tree<E> & T, unsigned &max, unsigned actual) {
00303     if ( T.Empty() ) {
00304         if (max < actual) {
00305             max = actual; // se deja el más grande de los 2
00306         }
00307         return;
00308     } else {
00309         for (unsigned i=T.Leftmost_N(); i <= T.Rightmost_N(); ++i) {
00310             Height0(T.Child(i), max, actual+1);
00311         }
00312         return;
00313     }
00314 } // Height0()
00315 
00316 /** Retorna la altura de \c "T".
00317   - La altura es la distanca desde \c "T" hasta la hoja más profunda en el
00318     sub-árbol formado por todos los descendientes de \c "T".
00319   - La altura de un nodo hoja siempre es cero.
00320   - <code> [ Is_Leaf(T) == true ] ==> [ Height(T) == 0 ] </code>
00321 
00322     \code
00323                                      [ Depth() Height() ]
00324     a [0 4]                a               [0 4]
00325     |--b [1 1]             |--b            [1 1]
00326     |  |--f [2 0]          |  |--f         [2 0]
00327     |  |--g [2 0]          |  |--g         [2 0]
00328     |  +--h [2 0]          |  +--h         [2 0]
00329     |--c [1 0]             |--c            [1 0]
00330     |--d [1 0]             |--d            [1 0]
00331     +--e [1 3]             +--e            [1 3]
00332        |--i [2 0]             |--i         [2 0]
00333        |--j [2 2]             |--j         [2 2]
00334        |  |--l [3 0]          |  |--l      [3 0]
00335        |  +--m [3 1]          |  +--m      [3 1]
00336        |     |--n [4 0]       |     |--n   [4 0]
00337        |     +--o [4 0]       |     +--o   [4 0]
00338        +--k [2 0]             +--k         [2 0]
00339     \endcode */
00340 template <class E>
00341 inline unsigned Height( const Tree<E> & T ) {
00342     unsigned actual,  max;
00343     max    = 0;
00344     actual = 0;
00345     Height0( T, max, actual );
00346     max = ( max > 0 ? max-1 : 0 );
00347     return max;
00348 } // Height()
00349 
00350 /** Retorna la longitud del camino desde \c "T" hasta la raíz del árbol.
00351     - Retorna la profundidad del sub-árbol respecto de su raíz
00352     - La profundidad de la raíz del árbol es cero.
00353     - <code> T.Empty() ==> [ Depth(T) == 0 ] </code> */
00354 template <class E>
00355 unsigned Depth( const Tree<E> & T ) {
00356     if ( T.Empty() ) {
00357         return 0;
00358     }
00359     unsigned n = 0;
00360     Tree<E> F = T;
00361     do {
00362         F = F.Father();
00363         ++n;
00364     } while ( ! F.Empty() );
00365     return n-1;
00366 } // Depth()
00367 
00368 /// Retorna la máxima cantidad de hijos que tienen \c "T" y todos sus sub-árboles.
00369 template <class E>
00370 unsigned Arity( Tree<E> & T ) {
00371     if ( T.Empty() ) {
00372         return 0;
00373     }
00374     unsigned max = 0, n_children = 0;
00375     Tree<E> Child = T.Leftmost();
00376     while ( ! Child.Empty() ) {
00377         unsigned n = Arity( Child );
00378         max = max > n ? max : n;
00379         n_children++;
00380         Child = Child.Right_Sibling();
00381     }
00382     return max > n_children ? max : n_children;
00383 } // Arity()
00384 
00385 /// Retorna \c "true" cuando el árbol es binario
00386 template <class E>
00387 bool Is_Binary( const Tree<E> & T ) {
00388     return Arity(T) <= 2;
00389 }
00390 
00391 #include <climits> // para UINT_MAX
00392 /** Esta función retorna el número de aristas que hay en
00393     el único camino que une la raíz de \c "n1" con la de \c "n2".
00394     - Si \c "n1" y \c "n2" pertenecen a árboles diferente,
00395       retorna \c UINT_MAX == \e infinito
00396 */
00397 template <class E>
00398 unsigned Length( const Tree<E> &n1, Tree<E> &n2 ) {
00399 /*
00400     1) Calcula L1 = Depth(n1)
00401     2) Calcula L2 = Depth(n2)
00402     3) Sincroniza profundidades, caminando hacia arriba en L2-L1 pasos (si L2>L1)
00403        para tratar de encontrar un ancestro comun "c" a "n1" y "n2":
00404                      r
00405                     /
00406                    /
00407             /     c         \
00408             |    / \        |
00409          L1 |   /   \    L2 |
00410             \  n1    \      |    \
00411                       \     |    | L2 - L1
00412                       n2    /    /
00413 
00414     4) En  un ciclo, pasa al padre de "n1" junto con el de "n2", buscando encontrar
00415        "c" un ancestro común. Cuenta [m == # iteraciones del ciclo]
00416     5) Si se llega a "r", lo que ocurre cuando el padre resulta ser el árbol vacío,
00417        quiere decir que "n1" y "n2" están en árboles diferentes, por lo que la distancia
00418        entre ellos no existe, o es infinita.
00419     6) Si existe el padre común "c", la distancia entre "n1" y "n2" es:
00420        2 * ( m ) + ( L2 - L1 ) 
00421 */
00422     bool Funcion_NO_implementada = false;
00423     assert( Funcion_NO_implementada );
00424     return UINT_MAX;
00425 } // Length()
00426 
00427 /** Transforma el árbol \c "T" que contiene como sub-árbol a\c "sT"
00428     para que la raíz de \c "T" sea \c "sT".
00429     - No hace nada si \c <code> T.Father().Emtpy() </code> [\c "T" ya es la raíz del árbol]
00430     - Traslada a \c Father() para que sea el hijo más izquierdo de manera que ocupe
00431       la posición "n-1" donde <code> n == Leftmost().Child_Number()" </code>
00432     - Traslada a los hermanos izquierdos para que estén antes de la antigua raíz
00433     - Traslada a los hermanos derechos para que estén después de la antigua raíz
00434 
00435     \code
00436            a                      e
00437           /|\                    /|\
00438         / / \ \                / / \ \
00439        b  c d  e              a  i j  k
00440       /|\     /|\            /|\
00441      f g h   i j k          b c d
00442                            /|\
00443                           f g h
00444     \endcode
00445      
00446     \pre
00447         - <code> Leftmost().Child_Number() > 0 </code>
00448         - <code> Ancestor(sT, T) == true </code> */
00449 template <class E>
00450 void New_Root( Tree<E>& T, Tree<E> &sT ) {
00451     bool Funcion_NO_implementada = false;
00452     assert( Funcion_NO_implementada );
00453     return;
00454 
00455     Tree<E> F = T.Father();
00456     if ( F.Empty() ) {
00457         return;
00458     }
00459     unsigned n = sT.Child_Number();
00460     if (n == 0) {
00461         return;
00462     }
00463     Tree<E> saveS = sT;
00464     Tree<E> newT = T;
00465     F.Graft(n, Tree<E>( ) ); // elimina "sT" del árbol "T"
00466     sT.Graft(n-1, newT);
00467     T.Move( sT );
00468     sT = saveS;
00469 } // New_Root()
00470 
00471 #endif  // Tree_Ex_h
00472 
00473 // EOF: Tree_Ex.h

Generado el Tue Jun 30 06:20:32 2009 para Uso de TL::Tree y TV::Tree: por  doxygen 1.3.9.1