lkptr
|
00001 // Bin_Tree.h (c) 2007 adolfo@di-mare.com 00002 00003 /** \file Bin_Tree.h 00004 \brief Arbol binario implementado con referencias \c lkptr<X> 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 #ifndef Bin_Tree_h 00013 #define Bin_Tree_h ///< Evita inclusión múltiple de \c "Bin_Tree.h" 00014 00015 #include "lkptr.h" 00016 #include <iostream> 00017 00018 template <class E> class Bin_Tree; // declaración hacia adelante para Bin_Tree_Node <> 00019 00020 /// Nodos almacenados en el árbol 00021 template <class E> 00022 class Bin_Tree_Node { 00023 public: 00024 template <class X> friend class Bin_Tree; // Sólo el árbol se le mete a este Rep 00025 typedef E value_type; ///< Nombre estándar del tipo de elemento contenido 00026 private: 00027 value_type m_data; ///< Valor almacenado en el nodo. 00028 lkptr< Bin_Tree_Node <E> > m_father; ///< Nodo padre (puede ser \c NULL si es raíz). 00029 lkptr< Bin_Tree_Node <E> > m_left; ///< Hijo izquierdo del árbol (\c NULL si es hoja). 00030 lkptr< Bin_Tree_Node <E> > m_right; ///< Hijo derecho del árbol (\c NULL si es hoja). 00031 private: 00032 /// Constructor a partir de un valor específico. 00033 Bin_Tree_Node( const value_type& d ) : m_data( d ), m_father(0), m_left(0), m_right(0) {} 00034 public: // debe ser público para que otros módulos puedan destruir árboles ya construidos. 00035 ~Bin_Tree_Node(); 00036 }; // Bin_Tree_Node 00037 00038 /** Los métodos para trabajar con árboles binarios regresan "referencias" que son sub-árboles. 00039 - Un sub-árbol es parte del árbol, por lo que al modificar los valores del 00040 sub-árbol también el árbol original queda cambiado. 00041 - Para evitar este tipo de modificación indirecta, es necesario trabajar 00042 con una "copia profunda" del árbol orignal, la que se puede obtener con 00043 \c copyDeep(). 00044 - Aún si el árbol original es eliminado, el sub-árbol continúa existiendo. 00045 - Debido a que los árboles y sub-árboles son referencias, en C++ es necesario mantener 00046 internamente "enlaces de referencia". 00047 00048 \dontinclude test_Bin_Tree.cpp 00049 \skipline test::multi_child() 00050 \until }} 00051 \see test_Bin_Tree<E>::test_multi_child() 00052 */ 00053 template <class E> 00054 class Bin_Tree { 00055 private: 00056 lkptr< Bin_Tree_Node<E> > m_root; ///< Un árbol "es" el puntero al nodo raíz. 00057 public: 00058 typedef E value_type; ///< Nombre estándar del tipo de elemento contenido 00059 typedef const value_type& const_reference; ///< Referencia constante al objeto contenido 00060 typedef unsigned size_type; ///< Nombre estándar del tipo retornado por \c size() 00061 00062 /// \name Constructores y destructor 00063 //@{ 00064 public: 00065 Bin_Tree() : m_root(0) {} ///< Constructor de vector: el árbol queda vacío. 00066 // Constructor de copia (no \c const). 00067 // Bin_Tree( Bin_Tree& other ) : m_root(0) { m_root.get() = const_cast< Bin_Tree_Node<E>* >(other.m_root); } 00068 Bin_Tree(const Bin_Tree& other) : m_root( other.m_root ) { } 00069 Bin_Tree(const value_type & d); 00070 ~Bin_Tree(); 00071 private: 00072 /// Constructor a partir de un puntero a un nodo. 00073 Bin_Tree( lkptr< Bin_Tree_Node<E> >& other ) : m_root(other) { } 00074 /// Constructor a partir de un puntero a un nodo (puntero \c const). 00075 Bin_Tree( const lkptr< Bin_Tree_Node<E> >& other ) : m_root(other) { } 00076 00077 //@} 00078 00079 /// \name Operaciones básicas 00080 //@{ 00081 public: 00082 bool isEmpty() const { return (m_root.get() == 0); } ///< Retorna \c "true" si el sub-árbol está vacío 00083 unsigned count() const ; 00084 unsigned countChildren() const ; 00085 /// Usa \c count() para retornar la cantidad de valores almacenados en el sub-árbol. 00086 unsigned size () const { return count(); } 00087 bool ok() const { return true; } ///< Verifica la invariante de \c Bin_Tree<E>. 00088 /// Usa \c ok() para verificar la invariante de la clase. 00089 template <class T> friend inline bool check_ok(const Bin_Tree<T>& aT); 00090 //@} 00091 00092 /// \name Operaciones de borrado 00093 //@{ 00094 public: 00095 /** Deja el árbol vacío. 00096 - Si es necesario, también elimina sus descendientes. 00097 - <code> T.left().erase(); // No cambia "T" porque el que cambia es "T.left()" </code> 00098 - <code> T.makeLeftChild( Bin_Tree<E>() ); // así sí se borra el hijo izquierdo </code> 00099 - <code> T.makeRightChild( Bin_Tree<E>() ); // borra el hijo derecho </code> 00100 00101 \par Complejidad: 00102 O( \c count() ) ==> tiempo <br> 00103 O( \c height() ) ==> espacio. 00104 \see http://www.di-mare.com/adolfo/binder/c04.htm#sc03 00105 */ 00106 void erase() { m_root.release(); } 00107 void clear() { erase(); } ///< Sinónimo de \c erase(). 00108 //@} 00109 00110 /// \name Operaciones de copiado 00111 //@{ 00112 public: 00113 /// Sinónimo de \c this->copy(o) (pero retorna \c *this). 00114 Bin_Tree& operator= ( const Bin_Tree & other ) { m_root = other.m_root; return *this; } 00115 void copy( const Bin_Tree & other ); 00116 /// Usa \c changeRoot() para sustituir por \c "d" el valor almacenado en la raíz del árbol. 00117 Bin_Tree& operator=( const value_type & d) { changeRoot(d); return *this; } 00118 void move( Bin_Tree & other ); 00119 void swap( Bin_Tree & other ); 00120 //@} 00121 00122 /// \name Métodos para cambiar los valores almacenados en el árbol 00123 //@{ 00124 public: 00125 void changeRoot( const value_type &d ); 00126 void changeLeftChild( const value_type &d ); 00127 void changeRightChild( const value_type &d ); 00128 void makeLeftChild( Bin_Tree T ); 00129 void makeRightChild( Bin_Tree T ); 00130 void releaseLeftChild( ); 00131 void releaseRightChild( ); 00132 void makeOrphan( ); 00133 //@} 00134 00135 /// \name Operaciones para usar los valores almacenados 00136 //@{ 00137 public: 00138 /// Valor almacenado en la raíz del sub-árbol 00139 /// \pre \c !isEmpty() 00140 value_type& data () const { return m_root->m_data; } 00141 /// Valor almacenado en la raíz del sub-árbol 00142 /// \pre \c !isEmpty() 00143 value_type& operator * () const { return m_root->m_data; } 00144 /// Puntero al valor almacenado en la raíz del sub-árbol 00145 /// \pre \c !isEmpty() 00146 value_type* operator -> () const { return &(m_root->m_data); } 00147 //@} 00148 00149 /// \name Operaciones de comparación 00150 //@{ 00151 public: 00152 /// ¿¿¿ (p == q) ??? 00153 template <class T> friend bool operator == (const Bin_Tree<T> &p, const Bin_Tree<T> &q); 00154 /// ¿¿¿ (p != q) ??? 00155 template <class T> friend bool operator != (const Bin_Tree<T> &p, const Bin_Tree<T> &q); 00156 bool equals( const Bin_Tree & o ) const { return (*this)==o; } ///< ¿¿¿ (*this==o) ??? 00157 /// Retorna \c true si \c "o" comparte la raíz con \c "*this" 00158 bool same( const Bin_Tree & o ) const { return m_root == o.m_root; } 00159 //@} 00160 00161 /// \name Métodos para recorrer el árbol 00162 //@{ 00163 public: 00164 const Bin_Tree root() const { return Bin_Tree( m_root ); } ///< Raíz del sub-árbol 00165 /** Acceso al padre. 00166 - Si el sub-árbol no tiene padre retorna el árbol vacío. 00167 - Como los árboles son referencias, este método no sirve para modificar 00168 la estructura del árbol. 00169 */ 00170 Bin_Tree father() const { 00171 if ( m_root.get() == 0 ) { return Bin_Tree(); } 00172 else { return Bin_Tree( m_root->m_father ); } 00173 } 00174 /** Acceso al hijo izquierdo. 00175 - Si el sub-árbol no tiene hijo izquierdo retorna el árbol vacío. 00176 - Permite cambiar el valor del hijo izquierdo si ese sub-árbol existe. 00177 - No sirve para agregarle un hijo a un árbol que no tiene hijo izquierdo. 00178 - Para agregar un sub-árbol como hijo izquierdo es necesario usar 00179 \c makeLeftChild(). 00180 - Como los árboles son referencias, este método no sirve para modificar 00181 la estructura del árbol. 00182 00183 \dontinclude test_Bin_Tree.cpp 00184 \skipline test::left_right() 00185 \until }} 00186 \see test_Bin_Tree<E>::test_left_right() 00187 */ 00188 Bin_Tree left() const { 00189 if ( m_root.get() == 0 ) { return Bin_Tree(); } 00190 // else if ( m_root->m_left == 0) { return Bin_Tree(); } 00191 else { return Bin_Tree( m_root->m_left ); } 00192 } 00193 00194 /** Acceso al hijo derecho. 00195 - Si el sub-árbol no tiene hijo derecho retorna el árbol vacío. 00196 - Permite cambiar el valor del hijo derecho si ese sub-árbol existe. 00197 - No sirve para agregarle un hijo a un árbol que no tiene hijo derecho. 00198 - Para agregar un sub-árbol como hijo derecho es necesario usar 00199 \c makeRightChild(). 00200 - Como los árboles son referencias, este método no sirve para modificar 00201 la estructura del árbol. 00202 00203 \dontinclude test_Bin_Tree.cpp 00204 \skipline test::left_right() 00205 \until }} 00206 \see test_Bin_Tree<E>::test_left_right() 00207 */ 00208 Bin_Tree right() const { 00209 if ( m_root.get() == 0 ) { return Bin_Tree(); } 00210 // else if ( m_root->m_right == 0) { return Bin_Tree(); } 00211 else { return Bin_Tree(m_root->m_right); } 00212 } 00213 /** Acceso al i-ésimo hijo del árbol. 00214 - Si el sub-árbol no tiene es hijo retorna el árbol vacío. 00215 - <code>( i == 0 )</code> ==> Hijo izquierdo. 00216 - <code>( i == 1 )</code> ==> Hijo derecho. 00217 - Como los árboles son referencias, este método no sirve para modificar 00218 la estructura del árbol. 00219 */ 00220 Bin_Tree child(int i) const { 00221 if ( m_root.get() == 0 ) { return Bin_Tree(); } 00222 else if (i==0) { return Bin_Tree(m_root->m_left); } 00223 else if (i==1) { return Bin_Tree(m_root->m_right); } 00224 else { return Bin_Tree(); } 00225 } 00226 //@} 00227 00228 /// \name Propiedades del árbol 00229 //@{ 00230 public: 00231 /** Retorna \c "true" si el árbol no tiene padre. 00232 - Retorna \c "false" para un árbol vacío. 00233 00234 \dontinclude test_Bin_Tree.cpp 00235 \skipline test::isRoot_isLeaf() 00236 \until }} 00237 \see test_Bin_Tree<E>::test_isRoot_isLeaf() 00238 */ 00239 bool isRoot() const { return ( m_root.get() == 0 ? false : m_root->m_father.get() == 0 ); } 00240 /** Retorna \c "true" si el árbol es una hoja. 00241 - Retorna \c "false" para un árbol vacío. 00242 00243 \dontinclude test_Bin_Tree.cpp 00244 \skipline test::isRoot_isLeaf() 00245 \until }} 00246 \see test_Bin_Tree<E>::test_isRoot_isLeaf() 00247 */ 00248 bool isLeaf() const { 00249 return ( m_root.get() == 0 ? false : (m_root->m_left.get() == 0) && (m_root->m_right.get() == 0) ); 00250 } 00251 /** Retorna \c "true" si el árbol es el hijo izquierdo de su padre. 00252 - Retorna \c "false" si el árbol está vacío. 00253 - Retorna \c "false" si el árbol no tiene padre. 00254 - Retorna \c "false" si el árbol es el hijo derecho de su padre. 00255 00256 \dontinclude test_Bin_Tree.cpp 00257 \skipline test::isLeft_isRight() 00258 \until }} 00259 \see test_Bin_Tree<E>::test_isLeft_isRight() 00260 */ 00261 bool isLeftChild() const { 00262 if ( m_root.isNull() ) { 00263 return false; // árbol vacío 00264 } 00265 else if ( m_root->m_father.get() != 0 ) { 00266 Bin_Tree_Node<E> * father = m_root->m_father.get(); 00267 return (m_root == father->m_left); 00268 } 00269 else { 00270 return false; // no es el hijo izquierdo 00271 } 00272 } 00273 /** Retorna \c "true" si el árbol es el hijo derecho de su padre. 00274 - Retorna \c "false" si el árbol está vacío. 00275 - Retorna \c "false" si el árbol no tiene padre. 00276 - Retorna \c "false" si el árbol es el hijo izquierdo de su padre. 00277 00278 \dontinclude test_Bin_Tree.cpp 00279 \skipline test::isLeft_isRight() 00280 \until }} 00281 \see test_Bin_Tree<E>::test_isLeft_isRight() 00282 */ 00283 bool isRightChild() const { 00284 if ( m_root.isNull() ) { 00285 return false; // árbol vacío 00286 } 00287 else if ( m_root->m_father.get() != 0 ) { 00288 Bin_Tree_Node<E> * father = m_root->m_father.get(); 00289 return (m_root == father->m_right); 00290 } 00291 else { 00292 return false; // no es el hijo derecho 00293 } 00294 } 00295 00296 /// Cantidad de referencias de la raíz del árbol 00297 unsigned use_count() const { return (m_root.get() == 0 ? 0 : m_root.use_count()); } 00298 //@} 00299 }; // Bin_Tree 00300 00301 /** \fn template <class E> inline Bin_Tree<E>::Bin_Tree(const Bin_Tree& o) 00302 \brief Constructor de copia: los dos árboles comparten la misma raíz. 00303 - Constructor de copia desde otro árbol (copia superficial). 00304 - Como un sub-árbol en realidad es una referencia, este método 00305 no hace la copia completa [profunda] del árbol. 00306 00307 \par Complejidad: 00308 O( \c 1 ). 00309 */ 00310 00311 /** Destructor. 00312 \par Complejidad: 00313 O( \c count() ) ==> tiempo <br> 00314 O( \c height() ) ==> espacio. 00315 \see http://www.di-mare.com/adolfo/binder/c04.htm#sc04 00316 */ 00317 template <class E> 00318 Bin_Tree<E>::~Bin_Tree() { // lkptr<> destruye el valor si hace falta 00319 m_root.release( ); // se auto-mata 00320 } 00321 00322 /// Destructor. 00323 template <class E> 00324 inline Bin_Tree_Node<E>::~Bin_Tree_Node() { 00325 m_father.release(); 00326 /* NOTA 00327 Cuando la estructura tiene ciclos puede ocurrir que al destruir 00328 uno de los elementos de la estructura se desencadene la destrucción 00329 de los demás, con lo que los valores terminan siendo destruidos más 00330 de una vez: 00331 A -> B -> C -> D -> // A mata a B que mata a C que mata a D 00332 /|\ | // y entonces D re-mata A etc... 00333 +---------<-------+ 00334 00335 En el caso de Bin_Tree<E> nunca hay ciclos, pues aunque cada nodo 00336 tiene punteros hacia arriba (m_father) y hacia abajo, a los hijos 00337 (m_left && m_right), nunca puede ocurrir que un nodo descendiente 00338 también sea padre de alguno de sus ancestros. 00339 00340 0 <== puntero nulo 00341 /|\ 00342 A 00343 / \ Nunca hay ciclos en el árbol 00344 B C 00345 / \ / \ 00346 0 0 0 0 <== punteros nulos 00347 */ 00348 } 00349 00350 /// Constructor a partir de un valor. 00351 template <class E> 00352 inline Bin_Tree<E>::Bin_Tree(const E & d) : m_root(0) { 00353 m_root.reset( new Bin_Tree_Node<E>(d) ); 00354 } 00355 00356 /** Copia superficial desde \c "o". 00357 - El valor anterior de \c "*this" se pierde. 00358 00359 \par Complejidad: 00360 O( \c 1 ). 00361 \returns *this. 00362 \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05 00363 */ 00364 template <class E> 00365 inline void Bin_Tree<E>::copy( const Bin_Tree & other ) { 00366 m_root = other.m_root; 00367 } 00368 00369 /** Intercambia los valores de \c "*this" y \c "o". 00370 - Debido a que algunos métodos retornan copias del valor de \c "*this" en 00371 lugar de una referencia, como ocurre con \c Bin_Tree::child(), a veces 00372 \c swap() no tiene el resultado esperado por el programador. 00373 - Por ejemplo, si se invoca <code> T.child(i). swap( T.child(j) ) </code> 00374 el resultado no es intercambiar los hijos, sino más bien intercambiar 00375 los valores de los sub-árboles temporales \c T.child(i) y \c T.child(j). 00376 La forma correcta de intercambiar hijos es usar \c makeLeftChild() y/o 00377 \c makeRightChild(). 00378 00379 \par Complejidad: 00380 O( \c 1 ). 00381 \returns *this. 00382 00383 \see http://www.di-mare.com/adolfo/binder/c04.htm#sc08 00384 00385 \dontinclude test_Bin_Tree.cpp 00386 \skipline test::move_swap() 00387 \until }} 00388 \see test_Bin_Tree<E>::test_move_swap() 00389 00390 \dontinclude test_Bin_Tree.cpp 00391 \skipline test::no_swap() 00392 \until }} 00393 \see test_Bin_Tree<E>::test_no_swap() 00394 */ 00395 template <class E> 00396 void Bin_Tree<E>::swap( Bin_Tree & other ) { 00397 if (this == &other) { 00398 return; // evita auto-copia 00399 } 00400 #if 1 00401 // Esta sí funciona porque no hace falta cambiar "m_father" en los hijos 00402 lkptr< Bin_Tree_Node<E> > tmp ( m_root ); 00403 m_root = other.m_root; 00404 other.m_root = tmp; 00405 #else 00406 Bin_Tree<E> TMP; // tmp está vacío 00407 TMP.move( *this ); // *this queda vacío 00408 this->move( other ); // ahora other está vacío 00409 other.move( TMP ); // ahora TMP vuelve a quedar vacío 00410 #endif 00411 return; 00412 } 00413 00414 /** Traslada a \c "*this" el valor de \c "other". 00415 - El valor anterior de \c "*this" se pierde. 00416 - El nuevo valor de \c "*this" es el que \c "other" tuvo. 00417 - \c "other" queda en el estado en que lo dejaría \c other.erase(). 00418 - Si \c "*this" es \c "other" entonces su valor no cambia. 00419 - En general, después de esta operación casi 00420 nunca ocurre que \c this->equal(other) es \c "true". 00421 00422 \par Complejidad: 00423 O( \c count() ) 00424 \returns *this. 00425 \see http://www.di-mare.com/adolfo/binder/c04.htm#sc07 00426 00427 \dontinclude test_Bin_Tree.cpp 00428 \skipline test::move_swap() 00429 \until }} 00430 \see test_Bin_Tree<E>::test_move_swap() 00431 */ 00432 template <class E> 00433 inline void Bin_Tree<E>::move( Bin_Tree & other ) { 00434 if (this == &other) { 00435 return; // evita auto-copia 00436 } 00437 m_root = other.m_root; 00438 other.m_root.release(); 00439 return; 00440 // Es O( count() ) porque a veces operator=() borra "*this" completo 00441 } 00442 /** Retorna la cantidad de valores almacenados en el sub-árbol. 00443 - Calcula el número de sub-árboles no vacíos del árbol. 00444 \par Complejidad: 00445 O( \c count() ) ==> tiempo <br> 00446 O( \c height() ) ==> espacio. 00447 \see http://www.di-mare.com/adolfo/binder/c05.htm#sc03 */ 00448 template <class E> 00449 unsigned Bin_Tree<E>::count() const { 00450 if (m_root.get() == 0) { 00451 return 0; 00452 } else { 00453 return 1 + ( left().count() + right().count() ); 00454 } 00455 } 00456 00457 /// Retorna la cantidad de hijos del árbol. 00458 /// \par Complejidad: 00459 /// O( \c 1 ) 00460 template <class E> 00461 unsigned Bin_Tree<E>::countChildren() const { 00462 if (m_root.get() == 0) { 00463 return 0; 00464 } 00465 int n = 0; 00466 if ( !left().isEmpty() ) { 00467 ++n; 00468 } 00469 if ( !right().isEmpty() ) { 00470 ++n; 00471 } 00472 return n; 00473 } 00474 00475 /// Sustituye por \c "d" el valor almacenado en la raíz del árbol. 00476 /// - Si el árbol está vacío, le agrega su raíz. 00477 template <class E> 00478 void Bin_Tree<E>::changeRoot( const value_type & d ) { 00479 if ( m_root.isNull() ) { // como el árbol está vacío hay que agregarle la raíz 00480 m_root.reset ( new Bin_Tree_Node<E>(d) ); // crea el nodo raíz 00481 } else { // como no hay más referencias.... 00482 m_root->m_data = d; // ... cambia el valor directamente 00483 } 00484 } 00485 00486 /** Sustituye por \c "d" el valor almacenado en el hijo izquierdo del árbol. 00487 - Si no existe el hijo izquierdo lo agrega como una hoja con valor \c "d". 00488 - Si ya existe el hijo izquierdo le sustituye su valor por \c "d". 00489 - No hace nada si el árbol \c "*this" está vacío. 00490 00491 \dontinclude test_Bin_Tree.cpp 00492 \skipline test::changeChild() 00493 \until }} 00494 \see test_Bin_Tree<E>::test_changeChild() 00495 */ 00496 template <class E> 00497 void Bin_Tree<E>::changeLeftChild( const value_type &d ) { 00498 if (m_root.get() == 0) { // ignora árboles vacíos 00499 return; 00500 } 00501 else if ( m_root->m_left.isNull() ) { 00502 m_root->m_left.reset( new Bin_Tree_Node<E>(d) ); // crea el nodo raíz 00503 m_root->m_left->m_father = m_root; // conecta el hijo hacia su padre 00504 } 00505 else { 00506 m_root->m_left->m_data = d; // cambia el valor almacenado 00507 } 00508 return; 00509 } 00510 00511 /** Sustituye por \c "d" el valor almacenado en el hijo derecho del árbol. 00512 - Si no existe el hijo derecho lo agrega como una hoja con valor \c "d". 00513 - Si ya existe el hijo derecho le sustituye su valor por \c "d". 00514 - No hace nada si el árbol \c "*this" está vacío. 00515 00516 \dontinclude test_Bin_Tree.cpp 00517 \skipline test::changeChild() 00518 \until }} 00519 \see test_Bin_Tree<E>::test_changeChild() 00520 */ 00521 template <class E> 00522 void Bin_Tree<E>::changeRightChild( const value_type &d ) { 00523 if (m_root.get() == 0) { // ignora árboles vacíos 00524 return; 00525 } 00526 else if ( m_root->m_right.isNull() ) { 00527 m_root->m_right.reset( new Bin_Tree_Node<E>(d) ); // crea el nodo raíz 00528 m_root->m_right->m_father = m_root; // conecta el hijo hacia su padre 00529 } 00530 else { 00531 m_root->m_right->m_data = d; // cambia el valor almacenado 00532 } 00533 return; 00534 } 00535 00536 /** Pone al árbol \c "T" como sub-árbol izquierdo de \c "*this". 00537 - Elimina el sub-árbol izquierdo de \c "*this" si \c "T" está vacío. 00538 - El sub-árbol \c "T" puede ser hijo de muchos árboles, pero el que 00539 es reportado como su padre es el último para el que se usó 00540 \c makeLeftChild(T) o \c makeRightChild(T). 00541 - El programador cliente debe ser cuidadoso para no introducir 00542 ciclos en sus árboles. 00543 00544 \pre <code> ! isEmpty() </code> 00545 00546 \dontinclude test_Bin_Tree.cpp 00547 \skipline test::no_swap() 00548 \until }} 00549 \see test_Bin_Tree<E>::test_no_swap() 00550 */ 00551 template <class E> 00552 void Bin_Tree<E>::makeLeftChild( Bin_Tree T ) { 00553 if ( ! m_root.isNull() /* && this->m_root != T.m_root */ ) { 00554 if ( ! T.m_root.isNull() ) { 00555 T.m_root->m_father = this->m_root; 00556 } 00557 m_root->m_left = T.m_root; // ahora sí es el hijo izquierdo 00558 } 00559 } 00560 00561 /** Pone al árbol \c "T" como sub-árbol derecho de \c "*this". 00562 - Elimina el sub-árbol derecho de \c "*this" si \c "T" está vacío. 00563 - El sub-árbol \c "T" puede ser hijo de muchos árboles, pero el que 00564 es reportado como su padre es el último para el que se usó 00565 \c makeLeftChild(T) o \c makeRightChild(T). 00566 - El programador cliente debe ser cuidadoso para no introducir 00567 ciclos en sus árboles. 00568 00569 \pre <code> ! isEmpty() </code> 00570 00571 \dontinclude test_Bin_Tree.cpp 00572 \skipline test::no_swap() 00573 \until }} 00574 \see test_Bin_Tree<E>::test_no_swap() 00575 */ 00576 template <class E> 00577 void Bin_Tree<E>::makeRightChild( Bin_Tree T ) { 00578 if ( ! m_root.isNull() /* && this->m_root != T.m_root */ ) { 00579 if ( ! T.m_root.isNull() ) { 00580 T.m_root->m_father = this->m_root; 00581 #if 0 00582 if ( ! T.m_root->m_father.isNull() ) { 00583 if ( T.m_root->m_father->m_left == T.m_root ) { 00584 T.m_root->m_father->m_left.release(); 00585 } 00586 else { 00587 T.m_root->m_father->m_right.release(); 00588 } 00589 } // "T" queda desconectado como hijo de su antiguo padre 00590 #endif 00591 } 00592 m_root->m_right = T.m_root; // ahora sí es el hijo derecho 00593 } 00594 #if 0 // implementación que no verifica que *this sea nulo 00595 m_root->m_right = T.m_root; 00596 if ( ! T.m_root.isNull() ) { 00597 T.m_root->m_father = this->m_root; 00598 } 00599 #endif 00600 } 00601 00602 /** Elimina el hijo izquierdo del árbol. 00603 - Es sinónimo de \c makeLeftChild( Bin_Tree<E>() ); 00604 00605 \dontinclude test_Bin_Tree.cpp 00606 \skipline test::releaseChild() 00607 \until }} 00608 \see test_Bin_Tree<E>::test_releaseChild() 00609 */ 00610 template <class E> 00611 inline void Bin_Tree<E>::releaseLeftChild( ) { 00612 makeLeftChild( Bin_Tree<E>() ); 00613 } 00614 00615 /** Elimina el hijo derecho del árbol. 00616 - Es sinónimo de \c makeLeftChild( Bin_Tree<E>() ); 00617 00618 \dontinclude test_Bin_Tree.cpp 00619 \skipline test::releaseChild() 00620 \until }} 00621 \see test_Bin_Tree<E>::test_releaseChild() 00622 */ 00623 template <class E> 00624 inline void Bin_Tree<E>::releaseRightChild( ) { 00625 makeRightChild( Bin_Tree<E>() ); 00626 } 00627 00628 /** Desconecta al hijo del padre. 00629 - Funciona con árboles vacíos. 00630 - El árbol \c "*this" continúa registrado como hijo de su padre. 00631 00632 \dontinclude test_Bin_Tree.cpp 00633 \skipline test::makeOrphan() 00634 \until }} 00635 \see test_Bin_Tree<E>::test_makeOrphan() 00636 */ 00637 template <class E> 00638 void Bin_Tree<E>::makeOrphan( ) { 00639 if ( ! m_root.isNull() ) { 00640 if ( m_root->m_father.isNull() ) { 00641 return; // ya está huérfano 00642 } 00643 #if 0 00644 else if ( m_root->m_father->m_left == m_root ) { 00645 // es el hijo izquierdo de su padre 00646 m_root->m_father->m_left.release(); 00647 } 00648 else { // assert( m_root->m_father->m_right == m_root ); 00649 // es el hijo derecho de su padre 00650 m_root->m_father->m_right.release(); 00651 } 00652 #endif 00653 m_root->m_father.release(); 00654 } 00655 } 00656 00657 #endif // Bin_Tree_h 00658 00659 // EOF: Bin_Tree.h