lkptr
|
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