Bin_Tree.h

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

Generado el Sat Jul 7 19:11:55 2007 para Implementacion de la clase Arbol_Rojinegro por  doxygen 1.4.7