lkptr - simple reference LinKed PoinTeR:
Bin_Tree_Lib.h
Go to the documentation of this file.
00001 // Bin_Tree_Lib.h (c) 2007 adolfo@di-mare.com
00002 
00003 /** \file  Bin_Tree_Lib.h
00004     \brief Funciones de apoyo para la clase \c Bin_Tree<E>.
00005 
00006     \author Adolfo Di Mare <adolfo@di-mare.com>
00007     \date   2007
00008 
00009     - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04
00010 */
00011 
00012 #include "Bin_Tree.h"
00013 #include <cassert>  // assert()
00014 #include <iostream> // cout
00015 #include <set>
00016 
00017 /** Retorna la longitud del camino desde \c "T" hasta la raíz del árbol.
00018     - Retorna la profundidad del sub-árbol respecto de su raíz.
00019     - La profundidad de la raíz del árbol es cero.
00020     - <code> [ T.isEmpty() ] ==> [ depth(T) == 0 ] </code>
00021     - <code> [ T.isEmpty() == true ] ==> [ height(T) == -1 ] </code>
00022 */
00023 template <class E>
00024 int depth( const Bin_Tree<E> & T ) {
00025     if ( T.isEmpty() ) {
00026         return -1;
00027     }
00028     unsigned n = 0;
00029     Bin_Tree<E> F = T;
00030     do {
00031         F = F.father();
00032         ++n;
00033     } while ( ! F.isEmpty() );
00034     return n-1;
00035 }
00036 
00037 /// Calcula la altura de sub-árbol.
00038 ///  - Esta función es el paso recursivo necesario para implementar \c height().
00039 ///  - Recorre recursivamente el árbol y recuerda la máxima profundidad encontrada en \c "max".
00040 ///  - \c "actual" es la profundidad del nodo actual.
00041 template <class E>
00042 void height_recurse( Bin_Tree<E> T, int &max, int actual ) {
00043     if ( T.isEmpty() ) {
00044         if (max < actual) {
00045             max = actual; // se deja el más grande de los 2
00046         }
00047     } else {
00048         height_recurse( T.left(),  max, actual+1 );
00049         height_recurse( T.right(), max, actual+1 );
00050     }
00051     return;
00052 }
00053 
00054 /** Retorna la altura de \c "T" o \c -1 si el árbol está vacío.
00055     - La altura es la distanca desde \c "T" hasta la hoja más profunda en el
00056       sub-árbol formado por todos los descendientes de \c "T".
00057     - La altura de un nodo hoja siempre es cero.
00058     - <code> [ T.isLeaf()  == true ] ==> [ height(T) == 0 ] </code>
00059     - <code> [ T.isEmpty() == true ] ==> [ height(T) == -1 ] </code>
00060 
00061     \code
00062                                      [ depth() height() ]
00063     a [0 4]                a               [0 4]
00064     |--b [1 1]             |--b            [1 1]
00065     |  |--f [2 0]          |  |--f         [2 0]
00066     |  +--h [2 0]          |  +--h         [2 0]
00067     +--e [1 3]             +--e            [1 3]
00068        |--i [2 0]             |--i         [2 0]
00069        +--j [2 2]             +--j         [2 2]
00070           |--l [3 0]             |--l      [3 0]
00071           +--m [3 1]             +--m      [3 1]
00072              |--n [4 0]             |--n   [4 0]
00073              +--o [4 0]             +--o   [4 0]
00074     \endcode */
00075 template <class E>
00076 inline int height( Bin_Tree<E> T ) {
00077     #if 1
00078         if( T.isEmpty() ) {
00079             return -1;
00080         }
00081         else {
00082             int hLeft  = height( T.left() );
00083             int hRigth = height( T.right() );
00084             return 1 + ( hLeft > hRigth ? hLeft : hRigth );
00085         }
00086     #else
00087         int actual,  max;
00088         max    = 0;
00089         actual = 0;
00090         height_recurse( T, max, actual );
00091     //  max = ( max > 0 ? max-1 : 0 );
00092         return max-1;
00093     #endif
00094 }
00095 
00096 /** Copia profunda de \c "other".
00097     - Copia todo el valor de \c "other" sobre \c "T", de forma que el nuevo valor de
00098       \c "*this" sea un duplicado exacto del valor de \c "other".
00099     - El valor anterior de \c "T" se pierde.
00100     - El objeto \c "other" mantiene su valor anterior.
00101     - Luego de la copia, cuando el valor de \c "other" cambia, el de \c "*this" no cambiará,
00102       y viceversa, pues la copia es una copia profunda; no es superficial.
00103     - Si \c "T" es \c "other" entonces su valor no cambia.
00104     - Después de esta operación siempre ocurre que <code> T == other </code>.
00105     \par Complejidad:
00106          O( \c T.count() ) + O( \c other.count() ).
00107     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05
00108 */
00109 template <class E>
00110 void copyDeep( Bin_Tree<E>& T, const Bin_Tree<E> &other ) {
00111     if ( &T == &other ) {
00112         return; // mismo árbol ==> evita auto-copia
00113     }
00114     else if ( other.isEmpty() ) { // si el otro está vacío
00115         T.erase();                // yo también quedo vacío
00116         return;
00117     }
00118     if ( T.same(other) ) {
00119     //  T.erase(); // mismo valor ==> borra a "T"
00120     }
00121 
00122     Bin_Tree<E> Root( other.data() ); // nueva raíz del árbol
00123 
00124     if ( ! other.left().isEmpty() ) { // copia el hijo izquierdo
00125         Bin_Tree<E> Child;
00126         copyDeep( Child, other.left() );
00127         Root.makeLeftChild( Child );
00128     }
00129 
00130     if ( ! other.right().isEmpty() ) { // copia el hijo derecho
00131         Bin_Tree<E> Child;
00132         copyDeep( Child, other.right() );
00133         Root.makeRightChild( Child );
00134     }
00135 
00136     T = Root;
00137 }
00138 
00139 /// Compara recursivamente los árboles \c "p" y \c "q".
00140 template <class E>
00141 bool comp(const Bin_Tree<E>& p, const Bin_Tree<E>& q) {
00142     if ( p.same(q) ) {
00143         return true;
00144     }
00145     if ( p.isEmpty() || q.isEmpty() ) { // son diferentes...
00146         return false; // ...pues sólo 1 está vácio
00147     }
00148     if ( ! (p.data() == q.data()) ) {
00149         return false; // valor diferente en la raíz
00150     }
00151     if ( ! comp( p.left(), q.left() ) ) {
00152         return false; // valor diferente en el sub-árbol izquierdo
00153     }
00154     if ( ! comp( p.right(), q.right() ) ) {
00155         return false; // valor diferente en el sub-árbol derecho
00156     }
00157 
00158     return true; // pues nunca encontró sub-árboles diferentes
00159 }
00160 
00161 /// Graba el valor del árbol como hilera Lisp: \c (a (b (f) (h)) (e (i) (k (l) (m (n) (o))))).
00162 template <class E>
00163 std::ostream& operator << ( std::ostream & COUT , const Bin_Tree<E> & T ) {
00164     if ( T.isEmpty() ) {
00165         return COUT;
00166     }
00167     {   COUT << '(' << *T; // raíz
00168         if ( ! T.left().isEmpty() ) {
00169             COUT << ' ';
00170             COUT << T.left();
00171         }
00172         if ( ! T.right().isEmpty() ) {
00173             COUT << ' ';
00174             COUT << T.right();
00175         }
00176         COUT << ')';
00177     }
00178     return COUT;
00179 }
00180 
00181 template <class E>
00182 inline bool operator == (const Bin_Tree<E> &p, const Bin_Tree<E> &q)
00183 { return comp( p , q ); }
00184 template <class E>
00185 inline bool operator != (const Bin_Tree<E> &p, const Bin_Tree<E> &q)
00186 { return !(p == q); }
00187 
00188 /** Cuenta la cantidad de valores almacenados en el árbol.
00189     - Cuenta conrrectamente aún si el árbol tiene ciclos.
00190     - El conjunto \c "S" registra cuáles sub-árboles fueron ya contados.
00191     - Lo usual es invocar \c S.clear() antes de invocar esta función.
00192 
00193     \dontinclude test_Bin_Tree.cpp
00194     \skipline    test::sizeStrong()
00195     \until       }}
00196     \see         test_Bin_Tree<E>::test_sizeStrong()
00197 */
00198 template <class E>
00199 int sizeStrong( const Bin_Tree<E>& T, std::set<E*> & S ) {
00200     if ( T.isEmpty() )  {
00201         return 0;
00202     }
00203     else if ( S.find( &T.data() ) == S.end() ) {
00204         S.insert( &T.data() );
00205         return 1 + sizeStrong( T.left() , S ) + sizeStrong( T.right() , S );
00206     }
00207     else {
00208         return 0;
00209     }
00210 }
00211 
00212 /// Usa \c T.ok() para verificar la invariante de \c Bin_Tree<E>
00213 template <class E>
00214 inline bool check_ok(const Bin_Tree<E>& T) {
00215     return T.ok();
00216 }
00217 
00218 /// Agrega una copia de \c "val" al árbol binario ordenado \c "T".
00219 /// - No agrega duplicados.
00220 template <class E>
00221 void orderedInsert( Bin_Tree<E> & T , const E& val ) {
00222 //  Versión no recursiva
00223     if ( T.isEmpty() ) {
00224         T.changeRoot( val );
00225         return;
00226     }
00227     Bin_Tree<E> Root = T; // Root es la raíz
00228     Bin_Tree<E> Child ( val ); // El nuevo sub-árbol hoja a insertar
00229     while ( ! Root.isEmpty() ) {
00230         if ( val < Root.data() ) {
00231             if ( Root.left().isEmpty() ) {
00232                 Root.makeLeftChild( Child );
00233                 break;
00234             }
00235             else {
00236                 Root = Root.left();
00237             }
00238         }
00239         else if ( val > Root.data() ) {
00240             if ( Root.right().isEmpty() ) {
00241                 Root.makeRightChild( Child );
00242                 break;
00243             }
00244             else {
00245                 Root = Root.right();
00246             }
00247         }
00248         else {
00249             break;  // DUPLICADO: no hace nada
00250         }
00251     }
00252     return;
00253 }
00254 
00255 /// Agrega una copia de \c "val" al árbol binario ordenado \c "T".
00256 /// - No agrega duplicados.
00257 ///
00258 /// \author Carlos Andres Gonzalez Vargas <cagv26@gmail.com>
00259 template <class E>
00260 void orderedInsert_Recursive( Bin_Tree<E> & T , const E& val ) {
00261     if ( T.isEmpty() ) { // Si el arbol esta vacío
00262         T.changeRoot( val ); // insertar el valor en el arbol
00263         return;
00264     }
00265     if ( val < T.data() ){ // si el valor del arbol es menor que le valor a insertar
00266         if ( T.left().isEmpty() ){ // si el hijo izquierdo esta vacio
00267             T.makeLeftChild( Bin_Tree<E>(val) ); // inserte un nuevo subarbol con el valor a insertar
00268             return;
00269         }
00270         else { //si el hijo izquierdo existe
00271             orderedInsert( T.left(), val ); //insertese ahora con el hijo izquierdo como base
00272         }
00273     }
00274     else if ( val > T.data() ) {//si el valor del arbol es mayor que le valor a insertar
00275         if ( T.right().isEmpty() ){//si el hijo derecho esta vacio
00276             T.makeRightChild(Bin_Tree<E> (val)); //inserte un nuevo subarbol con el valor a insertar
00277             return;//regresar
00278         }
00279         else { //si el hijo derecho existe
00280             orderedInsert(T.right(),val);//insertese ahora con el hijo derecho como base
00281         }
00282     }
00283     else {
00284         return; // no inserta duplicados
00285     }
00286     return; //regresar
00287 }
00288 
00289 /* Determina si existe un reordenamiento de los hijos del árbol \c T1 que resulta en el árbol \c T2.
00290    - Los siguientes árboles son homomorfos:
00291     \code
00292            a                     a              a
00293           / \                   / \            / \
00294          /   \                 /   \          /   \
00295         b     e               e     b        e     b
00296        / \   / \             / \   / \      / \   / \
00297       f   h i   k           k   i h   f    i   k f   h
00298                / \         / \                / \
00299               l   m       m  l               m   l
00300                  / \     / \                / \
00301                 n   o   o   n              n   o
00302     \endcode
00303 */
00304 template <class E>
00305 bool homomorfo( const Bin_Tree<E> & T1, const Bin_Tree<E> & T2 ) {
00306     if ( T1.isEmpty() && T2.isEmpty() ) {
00307         return true; // 2 árboles vacíos son homomorfos
00308     }
00309     if ( T1.isEmpty() || T2.isEmpty() ) {
00310         return false; // solo 1 de los 2 no está vacío
00311     }
00312     if ( T1.data() != T2.data() ) {
00313         return false; // valor diferente en la raíz del árbol
00314     }
00315 /*          T1                     T2
00316            /  \                   /  \
00317           /    \                 /    \
00318     T1_paco   T1_lola      T2_paco   T2_lola
00319 */
00320     Bin_Tree<E> T1_paco = T1.left();    Bin_Tree<E> T2_paco = T2.left();
00321     Bin_Tree<E> T1_lola = T1.right();   Bin_Tree<E> T2_lola = T2.right();
00322     if ( homomorfo( T1_paco,  T2_paco ) ) {
00323         if ( homomorfo( T1_lola,  T2_lola ) ) {
00324             return true;
00325         } if ( homomorfo( T1_paco,  T2_lola ) ) {
00326             return homomorfo( T1_lola,  T2_paco );
00327         }
00328         else {
00329             return false;
00330         }
00331     }
00332     else  if ( homomorfo( T1_paco, T2_lola ) ) {
00333         return homomorfo( T1_lola, T2_paco );
00334     }
00335     else { // assert( !homomorfo( T1_paco,  T2_paco ) && ! homomorfo( T1_paco, T2_lola ) );
00336         return false;
00337 
00338     }
00339 }
00340 
00341 /** Convierte a \c "T" en su sub-árbol espejo.
00342     - Recursivamente, sus hijos quedan en orden inverso del
00343       orden en el que  aparecían originalmente en \c "T".
00344 
00345     \code
00346            a                  a
00347           / \                / \
00348          /   \              /   \
00349         b     e            e     b
00350        / \   / \          / \   / \
00351       f   h i   k        k   i h   f
00352                / \      / \
00353               l  m      m   l
00354                 / \    / \
00355                n   o  o   n
00356     \endcode
00357 */
00358 template <class E>
00359 void mirror( Bin_Tree<E> T ) {
00360      if ( T.isEmpty() ) {
00361         return; // se sale si el árbol está vacío
00362     }
00363     // intercambia los hijos
00364     Bin_Tree<E> Left  = T.left();  // sostiene a cada hijo
00365     Bin_Tree<E> Right = T.right();
00366     T.makeLeftChild( Right ); // Pone el hijo derecho a la izquierda
00367     T.makeRightChild( Left ); // Pone el hijo izquierdo a la derecha
00368     mirror( Left  );
00369     mirror( Right ); // recursivamente modifica los hijos
00370 }
00371 
00372 // Graba en \c COUT en orden IPD el contenido del árbol binario \c "T".
00373 template <class E>
00374 void IPD( std::ostream & COUT, const Bin_Tree<E> & T ) {
00375     if ( T.isEmpty() ) {
00376         return; // porque ya terminó
00377     }
00378     IPD ( COUT , T.left() );
00379     COUT << " " << T.data();
00380     IPD ( COUT , T.right() );
00381 }
00382 
00383 /** Rota la raíz del arbol binario \c "K2" con su hijo izquierdo.
00384     \author Jorge Arturo Cordero Vargas <corderazo00@hotmail.com>
00385     \author Mark Allen Weiss
00386 \code
00387               [ K2 ]                 [ K1 ]
00388              /      \     ====\     /      \
00389             /        \    ====/    /        \
00390       [ K1 ]         /\           /\         [ K2 ]
00391      /      \       /  \         /  \       /      \
00392     /        \     /  Z \       / X  \     /        \
00393    /\        /\   /______\     /______\   /\        /\
00394   /  \      /  \                         /  \      /  \
00395  / X  \    /  Y \                       / Y  \    /  Z \
00396 /______\  /______\                     /______\  /______\
00397 \endcode
00398 */
00399 template <class E>
00400 Bin_Tree<E> rotateWithLeftChild( Bin_Tree<E> K2 ) {
00401     Bin_Tree<E> K1 = K2.left();      // AvlNode k1 = k2.left;
00402     K2.makeLeftChild(  K1.right() ); // k2.left = k1.right;
00403     K1.makeRightChild( K2 );         // k1.right = k2;
00404     return K1;                       // return k1;
00405 }
00406 
00407 /** Rota la raíz del arbol binario \c "K1" con su hijo derecho.
00408     \author Jorge Arturo Cordero Vargas <corderazo00@hotmail.com>
00409     \author Mark Allen Weiss
00410 \code
00411       [ K1 ]                                 [ K2 ]
00412      /      \             ====\             /      \
00413     /        \            ====/            /        \
00414    /\         [ K2 ]                 [ K1 ]         /\
00415   /  \       /      \               /      \       /  \
00416  / X  \     /        \             /        \     /  Z \
00417 /______\   /\        /\           /\        /\   /______\
00418           /  \      /  \         /  \      /  \
00419          / Y  \    /  Z \       / X  \    /  Y \
00420         /______\  /______\     /______\  /______\
00421 \endcode
00422 */
00423 template <class E>
00424 Bin_Tree<E> rotateWithRightChild( Bin_Tree<E> K1 ) {
00425     Bin_Tree<E> K2 = K1.right();     // AvlNode k2 = k1.right;
00426     K1.makeRightChild( K2.left() );  // k1.right = k2.left;
00427     K2.makeLeftChild(  K1 );         // k2.left = k1;
00428     return K2;                       // return k2;
00429 }
00430 
00431 /** Hace una rotacion doble con el hijo izquierda para el arbol binario \c "K3".
00432     - Primero rota el hijo izquierdo con su hijo derecho.
00433     - Luego \c "K3" con el nuevo hijo izquierdo.
00434 
00435     \author Jorge Arturo Cordero Vargas <corderazo00@hotmail.com>
00436     \author Mark Allen Weiss
00437 
00438 \code
00439               [ K3 ]                            [ K2 ]
00440              /      \                          /      \
00441             /        \                       /          \
00442       [ K1 ]         /\                    /              \
00443      /      \       /  \  ====\      [ K1 ]                [ K3 ]
00444     /        \     /  D \ ====/     /      \              /      \
00445    /\      [ K2 ] /______\         /        \            /        \
00446   /  \      /  \                  /\        /\          /\        /\
00447  / A  \    /    \                /  \      /  \        /  \      /  \
00448 /______\  /      \              / A  \    /  B \      / C  \    /  D \
00449          /\      /\            /______\  /______\    /______\  /______\
00450         /  \    /  \
00451        / B  \  /  C \
00452       /______\/______\         K1 <= K2 <= K3
00453 \endcode
00454 */
00455 template <class E>
00456 Bin_Tree<E> doubleWithLeftChild( Bin_Tree<E> K3 ) {
00457     K3.makeLeftChild( rotateWithRightChild( K3.left() ) ) ;
00458         // k3.left = rotateWithRightChild( k3.left );
00459     return rotateWithLeftChild( K3 );
00460         // return rotateWithLeftChild( k3 );
00461 }
00462 
00463 /** Hace una rotacion doble con el hijo de la derecha para el arbol binario \c "K1".
00464     - Primero rota el hijo derecho con su hijo izquierdo.
00465     - Luego \c "K3" con el nuevo hijo derecho.
00466 
00467     \author Jorge Arturo Cordero Vargas <corderazo00@hotmail.com>
00468     \author Mark Allen Weiss
00469 
00470 \code
00471       [ K1 ]                                    [ K2 ]
00472      /      \                                  /      \
00473     /        \                               /          \
00474    /\         [ K3 ]                       /              \
00475   /  \       /      \     ====\      [ K1 ]                [ K3 ]
00476  / A  \     /        \    ====/     /      \              /      \
00477 /______\ [ K2 ]      /\            /        \            /        \
00478           /  \      /  \          /\        /\          /\        /\
00479          /    \    /  D \        /  \      /  \        /  \      /  \
00480         /      \  /______\      / A  \    /  B \      / C  \    /  D \
00481        /\      /\              /______\  /______\    /______\  /______\
00482       /  \    /  \
00483      / B  \  /  C \
00484     /______\/______\           K1 <= K2 <= K3
00485 \endcode
00486 */
00487 template <class E>
00488 Bin_Tree<E> doubleWithRightChild( Bin_Tree<E> K1 ) {
00489     K1.makeRightChild( rotateWithLeftChild( K1.right() ) );
00490         // k1.right = rotateWithLeftChild( k1.right );
00491     return rotateWithRightChild( K1 );
00492         // return rotateWithRightChild( k1 );
00493 }
00494 
00495 /** Inserta el valor \c "val" en el árbol \c "T".
00496     - No agrega duplicados.
00497     - Usa inserción AVL para mantener a \c "T" balanceado.
00498 
00499     \author Jorge Arturo Cordero Vargas <corderazo00@hotmail.com>
00500     \author Mark Allen Weiss
00501     \date   2007
00502     \see http://www.cs.fiu.edu/~weiss/dsaajava/code/DataStructures/AvlTree.java
00503 */
00504 template <class E>
00505 void insertAVL( Bin_Tree<E> & T, const E & val ) {
00506     if ( T.isEmpty() ) {
00507         T.changeRoot( val );
00508     }
00509     else if ( val  < T.data() ) {
00510         if ( T.left().isEmpty() ) {
00511             T.makeLeftChild( Bin_Tree<E>(val) );
00512         }
00513         else {
00514             Bin_Tree<E> Left = T.left();
00515             insertAVL( Left , val );
00516             T.makeLeftChild( Left );
00517         }
00518         if ( height(T.left())-height(T.right()) == 2 ) {
00519             if ( val < T.left().data() ) {
00520                 T = rotateWithLeftChild( T );
00521             }
00522             else {
00523                 T = doubleWithLeftChild( T );
00524             }
00525         }
00526     }
00527     else if ( val > T.data() ) {
00528         if ( T.right().isEmpty() ) {
00529             T.makeRightChild( Bin_Tree<E>(val) );
00530         }
00531         else {
00532             Bin_Tree<E> Right = T.right();
00533             insertAVL( Right , val );
00534             T.makeRightChild( Right );
00535         }
00536         if ( height(T.right())-height(T.left()) == 2 ) {
00537             if ( val > T.right().data() ) {
00538                 T = rotateWithRightChild( T );
00539             }
00540             else {
00541                 T = doubleWithRightChild( T );
00542             }
00543         }
00544     }
00545     else {
00546         ;  // DUPLICADO: no hace nada
00547     }
00548     return;
00549 /*
00550     El método \c insertAVL() deberá insertar en un árbol binario un valor no repetido,
00551     y asegurarse de que el árbol se encuentre siempre balanceado, esto es, que en
00552     ninguno de sus nodos la altura del subárbol derecho y la del subárbol izquierdo
00553     difieran en mas de 1 nivel.
00554 
00555     Para esto, se buscó un algoritmo en internet
00556     - http://www.cs.fiu.edu/~weiss/dsaajava/code/DataStructures/AvlTree.java
00557     que cumpliera con la especificación de la tarea. Este algoritmo se encarga de
00558     insertar un nodo en el árbol con insert(), y determinar, de ser necesario, el
00559     tipo y dirección de la rotación que se debe hacer en éste, ya sea unitaria
00560     con las funciones \c rotateWithLeftChild() y  \c rotateWithRightChild(), o
00561     dobles con \c doubleWithLeftChild() y \c doubleWithLeftChild(); para
00562     reestablecer el balance del árbol.
00563 */
00564 }
00565 
00566 /** \fn    template <class E> void deleteAVL( Bin_Tree<E> & T , const E& val );
00567     \brief Elimina el valor \c "val" del árbol \c "T".
00568     - Usa borrado AVL para mantener a \c "T" balanceado.
00569 */
00570 template <class E>
00571 void deleteAVL( Bin_Tree<E> & T , const E & val );
00572 
00573 /** \fn    template <class E> void balanceAVL( Bin_Tree<E> & T );
00574     \brief Balancea el árbol ordenado \c "T" si está desbalanceado.
00575 */
00576 template <class E>
00577 void balanceAVL( Bin_Tree<E> & T );
00578 
00579 /// Verifica que \c "T" es un árbol ordendao ascendentemente.
00580 template <class E>
00581 bool isAscending( const Bin_Tree<E> & T ) {
00582     if ( T.isEmpty() ) {
00583         return true;
00584     }
00585     if ( ! isAscending( T.left() ) ) {
00586         return false;
00587     }
00588     if ( ! isAscending( T.right() ) ) {
00589         return false;
00590     }
00591     // verifica que los hijos estén correctamente ordenados
00592     if ( ! T.left().isEmpty() ) {
00593          if ( ! ( T.left().data() <= T.data() ) ) {
00594               return false; // hijo izquierdo desordenado
00595          }
00596     }
00597     if ( ! T.right().isEmpty() ) {
00598          if ( ! ( T.right().data() >= T.data() ) ) {
00599               return false; // hijo derecho desordenado
00600          }
00601     }
00602     return true;
00603 }
00604 
00605 /// Verifica que \c "T" es un árbol balanceado AVL ascendente.
00606 template <class E>
00607 bool isAVL( const Bin_Tree<E> & T ) {
00608     if ( T.isEmpty() ) {
00609         return true;
00610     }
00611     if ( ! isAVL( T.left() ) ) {
00612         return false;
00613     }
00614     if ( ! isAVL( T.right() ) ) {
00615         return false;
00616     }
00617 
00618     // verifica que la altura de los hijos difiera en 1 como máximo
00619     int left  = height( T.left() );
00620     int right = height( T.right() );
00621     int diff = ( left > right ? left-right : right-left );
00622     if (diff > 1) {
00623         return false;
00624     }
00625 
00626     // verifica que los hijos estén correctamente ordenados
00627     if ( ! T.left().isEmpty() ) {
00628          if ( ! ( T.left().data() <= T.data() ) ) {
00629               return false; // hijo izquierdo desordenado
00630          }
00631     }
00632     if ( ! T.right().isEmpty() ) {
00633          if ( ! ( T.right().data() >= T.data() ) ) {
00634               return false; // hijo derecho desordenado
00635          }
00636     }
00637     return true;
00638 }
00639 
00640 #if 0
00641     template <class E>
00642     void balanceAVL( Bin_Tree<E> & T ) {
00643     }
00644     template <class E>
00645     void insertAVL( Bin_Tree<E> & T , const E& val ) {
00646         orderedInsert( T , val );
00647         balanceAVL(T);
00648     }
00649     template <class E>
00650     void deleteAVL( Bin_Tree<E> & T , const E& val) {
00651         orderedDelete( T , val );
00652         balanceAVL(T);
00653     }
00654 #else
00655 //  #include "A41369-A55609.h"
00656     #include "A52512.h"
00657 //  #include "A54641.h"
00658 #endif
00659 
00660 // EOF: Bin_Tree_Lib.h
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines