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

Generado el Sun Feb 19 09:37:34 2006 para Uso de TL::Tree y TV::Tree: por  doxygen 1.3.9.1