lkptr - simple reference LinKed PoinTeR:
Bin_Tree.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines