Página principal | Lista de namespace | Lista de componentes | Lista de archivos | Miembros del Namespace  | Miembros de las clases | Archivos de los miembros | Páginas relacionadas

Tree_V.h

Ir a la documentación de este archivo.
00001 // Tree_V.h (c) 2004 adolfo@di-mare.com
00002 
00003 /** \file Tree_V.h
00004     \brief Declaraciones y definiciones para la clase \c Tree
00005 
00006     \author Adolfo Di Mare <adolfo@di-mare.com>
00007     \date    2004
00008 
00009     - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04
00010 */
00011 
00012 #ifndef Tree_V_h
00013 #define Tree_V_h
00014 
00015 #ifndef NDEBUG // ==> Overview of File Translation ==> C++
00016     #define USE_v_Alive
00017     #undef  USE_v_Alive
00018 #endif
00019 
00020 #include <cassert> // para usar assert()
00021 
00022 /// Arboles de adolfo@di-mare.com cuyos nodos contienen un vector de punteros a sus hijos
00023 namespace TV {
00024 
00025 template <class E> class Tree;
00026 template <class E> bool check_ok( const E & );
00027 template <class E> bool check_ok( const Tree<E>& T); // declaration hacia adelante
00028 
00029 /// Nodos almacenados en el árbol.
00030 template <class E>
00031 class Tree_Node {
00032 public:
00033     friend class Tree<E>;
00034     typedef E value_type; ///< Nombre estándar del tipo de elemento contenido
00035 private:
00036     Tree_Node( const value_type& d ) : m_data( d ), m_refCount(1), m_n_child(0), m_father(0) {} ///< Constructor de vector
00037     static Tree_Node* Get_New(const E& d);
00038     void No_Children() { for (unsigned i=0; i < N; ++i) { m_Lchild[i]= 0; } } ///< Pone en nulo todos los punteros a los hijos porque ni \c Get_New() ni el constructor lo hacen
00039 private:
00040     static const unsigned N = 15; ///< Cantidad máxima de hijos por nodo
00041     value_type  m_data; ///< Valor almacenado en el nodo
00042     unsigned    m_refCount; ///< Cantidad de punteros hacia mi
00043     int         m_n_child; ///< Soy el el hijo número \c "m_n_child" de mi padre
00044     Tree_Node * m_father; ///< Puntero al nodo padre
00045     Tree_Node * m_Lchild[N]; ///< Punteros a cada uno de los hijos
00046 private:
00047     #ifdef USE_v_Alive // ==> NDEBUG ==> Overview of File Translation ==> C++
00048         static const unsigned N_Alive = 1033; ///< Cantidad máxima posible de punteros en uso
00049         static Tree_Node *    m_v_Alive[N_Alive]; ///< Punteros en uso
00050         static unsigned       m_n_Alive; ///< Cantidad de punteros en uso
00051     #endif
00052 }; // Tree_Node
00053 
00054 /** Los métodos para trabajar con árboles regresan "referencias" que son sub-árboles.
00055     - Un sub-árbol es parte del árbol, por lo que al modificar los valores del
00056       sub-árbol también el árbol original queda cambiado.
00057     - Para evitar este tipo de modificación indirecta, es necesario trabajar
00058       con una "copia profunda" del árbol orignal, la que se puede obtener con
00059       \c Tree<E>::Copy_Deep().
00060     - Aún si el árbol original es eliminado, el sub-árbol continúa existiendo
00061     - Debido a que los árboles y sub-árboles son referencias, en C++ es necesario mantener
00062       internamente "cuentas de referencia" que impiden que métodos como \c Father() o \c Root()
00063       sean métodos <code>const</code>.
00064     - Muchos métodos retornan referencias \c Tree& porque es más eficiente, pues cada
00065       vez que un \c Tree es copiado hay que actualizar la "cuenta de referencia" de
00066       la raíz del sub-árbol. */
00067 template <class E>
00068 class Tree {
00069 public:
00070     typedef E value_type; ///< Nombre estándar del tipo de elemento contenido
00071 private:
00072     static const unsigned N = Tree_Node<E>::N; ///< Cantidad máxima de hijos por nodo
00073 
00074 /// \name Constructores y destructor
00075 //@{
00076 public:
00077     Tree() : m_root(0) {} ///< Constructor de vector
00078     Tree(const Tree& o);
00079     Tree(const value_type & d);
00080     ~Tree();
00081 private:
00082     /// Constructor a partir de un nodo
00083     Tree(Tree_Node<E>* p) : m_root(p) { if (p!=0) { p->m_refCount++; } }
00084     /// Truco para usar el constructor que no verifica <code> (p != 0) </code>
00085     typedef void NOT_null_pointer;
00086     /// Constructor a partir de un nodo [ requiere <code> p != 0 </code> ]
00087     Tree(NOT_null_pointer* p) : m_root( (Tree_Node<E>*)p) { // assert( p != 0 );
00088         ((Tree_Node<E>*)p)->m_refCount++; }
00089 //@}
00090 
00091 /// \name Operaciones básicas
00092 //@{
00093 public:
00094     bool     Empty() const { return (m_root == 0); } ///< Retorna \c "true" si el sub-árbol está vacío
00095     unsigned Count() const ;
00096     unsigned Count_Children() const ;
00097     unsigned Size () const { return Count(); } ///< Usa \c Count() para retornar la cantidad de valores almacenados en el sub-árbol
00098     friend bool check_ok<E>(const Tree<E>& T);
00099     bool        Ok() { return check_ok(*this); } ///< Usa \c check_ok(Tree& T) para verificar la invariante de \c Tree
00100 //@}
00101 
00102 /// \name Operaciones de borrado
00103 //@{
00104 public:
00105     void Erase();
00106     void Erase_Son(unsigned n) { Tree T; Graft(n, T); }
00107 //@}
00108 
00109 /// \name Operaciones de copiado
00110 //@{
00111 public:
00112     Tree& operator= (const Tree &o) { return Copy(o); } ///< Sinónimo de \c this->Copy(o)
00113     Tree& Copy (const Tree &o);
00114     Tree& Move (Tree &o);
00115     Tree& Swap (Tree &o);
00116     Tree& Copy_Deep( const Tree &o );
00117     /// Usa \c Change_Root() para sustituir por "d" el valor almacenado en la raíz del árbol
00118     Tree& operator=( const value_type & d) { Change_Root(d); return *this; }
00119 //@}
00120 
00121 /// \name Métodos para cambiar los valores almacenados en el árbol
00122 //@{
00123 public:
00124     Tree Change_Root(const value_type &d);
00125     Tree Change_Child( unsigned n, const value_type &d );
00126     Tree Change_Left_Sibling_Inmediate( const value_type &d );
00127     Tree Change_Right_Sibling_Inmediate( const value_type &d );
00128     Tree Graft( unsigned n, Tree &o );
00129 //@}
00130 
00131 /// \name Operaciones para usar los valores almacenados
00132 //@{
00133 public:
00134     value_type& Data        () { return  m_root->m_data;  } ///< Valor almacenado en la raíz del sub-árbol
00135     value_type& operator *  () { return   Data();  } ///< Valor almacenado en la raíz del sub-árbol
00136     value_type* operator -> () { return &(m_root->m_data); } ///< Puntero al valor almacenado en la raíz del sub-árbol
00137     const value_type& Data        () const { return  m_root->m_data;  } ///< Valor almacenado en la raíz del sub-árbol
00138     const value_type& operator *  () const { return   Data();  } ///< Valor almacenado en la raíz del sub-árbol
00139     const value_type* operator -> () const { return &(m_root->m_data); } ///< Puntero al valor almacenado en la raíz del sub-árbol
00140 //@}
00141 
00142 /// \name Operaciones de comparación
00143 //@{
00144 public:
00145     template <class X> friend bool operator == (const Tree<X> &p, const Tree<X> &q); ///< ¿¿¿ (p == q) ???
00146     template <class X> friend bool operator != (const Tree<X> &p, const Tree<X> &q); ///< ¿¿¿ (p != q) ???
00147     bool Equals( const Tree & o ) const { return (*this)==o; } ///< ¿¿¿ (*this==o) ???
00148     /// Retorna \c true si \c "o" comparte la raíz con \c "*this"
00149     bool Same( const Tree & o ) const { return m_root == o.m_root; }
00150 //@}
00151 
00152 /// \name Métodos para recorrer el árbol
00153 //@{
00154 public:
00155     Tree Root() const { return Tree( m_root ); } ///< Raíz del sub-árbol
00156     Tree Father() const ;
00157     Tree Child(unsigned n) const;
00158     Tree Left() const;
00159     Tree Right() const;
00160     Tree Leftmost() const;
00161     Tree Rightmost() const;
00162     Tree Sibling(int n) const;
00163     Tree Left_Sibling() const;
00164     Tree Right_Sibling() const;
00165     Tree Previous_Sibling() const { return Left_Sibling(); } ///<  Sinónimo de \c Left_Sibling()
00166     Tree Prev_Sibling() const { return Left_Sibling(); } ///<  Sinónimo de \c Left_Sibling()
00167     Tree Next_Sibling() const { return Right_Sibling(); } ///<  Sinónimo de \c Right_Sibling()
00168     Tree Right_Sibling_Inmediate() const;
00169     Tree Left_Sibling_Inmediate() const;
00170 //@}
00171 
00172 /// \name Propiedades del árbol
00173 //@{
00174 public:
00175     /// Retorna \c "n" si \c "*this" es el n-ésimo hijo de su padre, si no retorna \c 0 (cero)
00176     unsigned Child_Number() const { return ( m_root==0 ? 0 : m_root->m_n_child ); }
00177     /// Retorna \c "n" si el hijo más izquierdo de \c "*this" es el n-ésimo hijo, si no retorna \c 0 (cero)
00178     unsigned Leftmost_N() const { return Leftmost().Child_Number(); }
00179     /// Retorna \c "n" si el hijo más derecho de \c "*this" es el n-ésimo hijo, si no retorna \c 0 (cero)
00180     unsigned Rightmost_N() const { return Rightmost().Child_Number(); }
00181     /// Retorna \c "true" si el árbol es una hoja
00182     bool Is_Leaf() const { return ( ! Empty() && Leftmost().Empty() ); }
00183     /// Retorna \c "true" si el árbol no tiene padre
00184     bool Is_Root() const { return ( m_root != 0  && m_root->m_father == 0 ); }
00185     /// Cantidad de referencias de la raíz del árbol
00186     unsigned use_count() const { return (m_root==0 ? 0 : m_root->m_refCount); }
00187 //@}
00188 
00189 /// \name Funciones para manipular valores a bajo nivel
00190 //@{
00191 private:
00192     /// Convierte el puntero al nodo en un referencia a \c Tree
00193     static Tree& CastTo_Tree_Ref ( Tree_Node<E> * &p )
00194     { return (Tree&) *( reinterpret_cast<Tree*> (&p)); }
00195 //@}
00196 
00197 /// \name Funciones recursivas que realizan el trabajo sobre nodos
00198 //@{
00199 private:
00200     static void Erase0(Tree_Node<E> * p);
00201     static bool Comp0(const Tree_Node<E> *p, const Tree_Node<E> *q);
00202     static void Count0(const Tree_Node<E> * p, unsigned & n);
00203     static Tree_Node<E>* Copy_Deep0(Tree_Node<E> * father, const Tree_Node<E> * p);
00204 //@}
00205 private:
00206     Tree_Node<E> * m_root; ///< Un árbol "es" el puntero al nodo raíz
00207 }; // Tree
00208 
00209 #ifdef USE_v_Alive
00210     unsigned Tree<E>::Tree_Node<E>::m_n_Alive = 0; // Hay que "repetir" estos nombres acá para que el ...
00211     Tree_Node<E>* Tree<E>::Tree_Node<E>::m_v_Alive[Tree<E>::Tree_Node<E>::N_Alive]; // ... compilador les asigne memoria
00212 #endif
00213 
00214 /** Crea un nuevo nodo y lo inicializa con \c "d".
00215     - Para mejorar la eficiencia, no incializa los punteros a los hijos.
00216     - Si la macro \c USE_v_Alive de compilación existe, también agrega el nuevo
00217       nodo al contenedor global \c Tree<E>::m_v_Alive[], de manera que es posible
00218       saber si un puntero a un nodo está o no en uso.
00219     - En realidad sobra usar este método, pero la utilidad de usarlo es
00220       que es posible examinar \c Tree<E>::m_v_Alive[] para saber si los métodos
00221       de árbol están correctamente implementados. */
00222 template <class E>
00223 inline Tree_Node<E> * Tree_Node<E>::Get_New( const E& d) {
00224     Tree_Node<E>* p = new Tree_Node(d);
00225     #ifdef USE_v_Alive
00226         m_v_Alive[m_n_Alive] = p;
00227         m_n_Alive++;
00228     #endif
00229     return p;
00230 }
00231 
00232 /**  Constructor de copia desde otro árbol (copia superficial).
00233     - Como un sub-árbol en realidad es una referencia, este método
00234       no hace la copia completa [profunda] del árbol. */
00235 template <class E>
00236 inline Tree<E>::Tree(const Tree& o) {
00237     if (o.m_root != 0) {
00238         o.m_root->m_refCount++; // una referencia más porque "o" y "*this" ...
00239     }
00240     m_root =  o.m_root; // ... ahora comparten la raíz
00241 }
00242 
00243 /**  Destructor.
00244     \par Complejidad:
00245          O( \c Count() )
00246 
00247     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc04 */
00248 template <class E>
00249 inline Tree<E>::~Tree() {
00250     if (m_root != 0) { Erase0(m_root); }
00251 }
00252 
00253 /// Constructor a partir de un valor.
00254 template <class E>
00255 inline Tree<E>::Tree(const E& d) {
00256     m_root = Tree_Node<E>::Get_New(d);
00257     m_root->No_Children(); // ... pues el constructor no inicializa los punteros a los hijos
00258 }
00259 
00260 /** Copia superficial desde \c "o".
00261     - El valor anterior de \c "*this" se pierde.
00262 
00263     \par Complejidad:
00264          O( \c Count() )
00265 
00266     \returns *this
00267 
00268     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05 */
00269 template <class E>
00270 Tree<E>& Tree<E>::Copy( const Tree &o ) {
00271     if (m_root != o.m_root) { // evita auto-borrado
00272         if (m_root != 0) {
00273             Erase0(m_root); // borra el valor actual
00274         }
00275         m_root =  o.m_root; // comparte la raíz
00276         if (o.m_root != 0) {
00277             o.m_root->m_refCount++; // una referencia más
00278         }
00279     }
00280     return *this;
00281 }
00282 
00283 /** Traslada el valor de \c "o" a \c "*this".
00284   - El valor anterior de \c "*this" se pierde
00285   - El nuevo valor de \c "*this" es el que \c "o" tuvo
00286   - \c "o" queda en el estado en que lo dejaría \c Erase()
00287   - Si \c "*this" es \c "o" entonces su valor no cambia
00288   - En general, después de esta operación casi
00289     nunca ocurre que <code> (*this == o) </code>
00290 
00291     \par Complejidad:
00292          O( \c Count() )
00293 
00294     \returns \c *this
00295 
00296     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc07 */
00297 template <class E>
00298 Tree<E>& Tree<E>::Move( Tree &o ) {
00299     if (m_root == o.m_root) { // evita auto-borrado
00300         if (m_root != 0) {
00301             Erase0(m_root); // borra el valor actual
00302         }
00303         m_root = o.m_root; // se roba los hijos
00304         o.m_root = 0; // anula al dador
00305     }
00306     return *this;
00307 }
00308 
00309 /** Intercambia los valores de \c "*this" y \c "o".
00310     - Debido a que algunos métodos retornan copias del valor de \c "*this" en
00311       lugar de una referencia, como ocurre con \c Tree<E>::Child(), a veces
00312       \c Swap() no tiene el resultado esperado por el programador.
00313     - Por ejemplo, si se invoca <code> T.Child(i). Swap( T.Child(j) ) </code>
00314       el resultado no es intercambiar los hijos, sino más bien intercambiar
00315       los valores de los sub-árboles temporales \c T.Child(i) y \c T.Child(j).
00316       La forma correcta de intercambiar hijos es usar \c Graft().
00317 
00318       \par Complejidad:
00319          O( \c 1 )
00320 
00321     \returns *this
00322 
00323     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc08 */
00324 template <class E>
00325 inline Tree<E>& Tree<E>::Swap( Tree &o ) {
00326     Tree_Node<E> * tmp = m_root;
00327     m_root = o.m_root;
00328     o.m_root = tmp;
00329     return *this;
00330 }
00331 
00332 /** Acceso al padre.
00333     - Si el sub-árbol no tiene padre retorna el árbol vacío.
00334 
00335     \par Complejidad:
00336          O( \c 1 ) */
00337 template <class E>
00338 inline Tree<E> Tree<E>::Father() const {
00339     if (m_root == 0) {
00340         return Tree( );
00341     } else {
00342         return Tree( m_root->m_father );
00343     }
00344 }
00345 
00346 /** Acceso al \c "n"-ésimo hijo.
00347     - Si el sub-árbol no tiene un hijo número \c "n" retorna el sub-árbol vacío.
00348 
00349     \par Complejidad:
00350          O( \c 1 ) */
00351 template <class E>
00352 Tree<E> Tree<E>::Child( unsigned n ) const {
00353     if (n >= Tree<E>::N) {
00354         return Tree( );
00355     }
00356     if (m_root == 0) { // ignora árboles vacíos
00357         return Tree( );
00358     }
00359     return Tree ( m_root->m_Lchild[n] );
00360 }
00361 
00362 /** Sub-árbol izquierdo [en un árbol binario].
00363     - Sinónimo de \c Child(0).
00364     \par Complejidad:
00365          O( \c 1 ) */
00366 template <class E>
00367 inline Tree<E> Tree<E>::Left() const {
00368     if (m_root == 0) {
00369         return Tree( );
00370     } else {
00371         return Tree( m_root->m_Lchild[0] );
00372     }
00373 }
00374 
00375 /** Sub-árbol derecho [en un árbol binario].
00376     - Sinónimo de \c Child(1).
00377 
00378     \par Complejidad:
00379          O( \c 1 ) */
00380 template <class E>
00381 inline Tree<E> Tree<E>::Right() const {
00382     if (m_root == 0) {
00383         return Tree( );
00384     } else {
00385         return Tree( m_root->m_Lchild[1] );
00386     }
00387 }
00388 
00389 /** \typedef Tree<E>::NOT_null_pointer
00390     \brief Truco para evitar comparar con \c 0 ( \c nil )
00391     al usar \c Tree_Node<E>* para construir \c Tree().
00392 
00393     Al implementar cada uno de los métodos de \c Tree con frecuencia ocurre
00394     que es posible saber que el sub-árbol retornado no está vacío. En estos casos, conviene
00395     usar un contructor que no verifique si la raíz del árbol es nula.
00396 
00397     Esta clase se usa como una marca para que se ejecute el contructor
00398     <code> Tree<E>::Tree(NOT_null_pointer* p) </code>
00399     que no verifica la nulidad de \c "m_root"; esta es una micro-eficiencia, pero aquí sirve
00400     para mostrar un truco que es muy usado en C++ para aumentar la eficiencia de los
00401     programas, pues le permite al programado usar la sobrecarga de operadores para evitar
00402     repetir verificaciones innecesarias.
00403 
00404     \see http://www.di-mare.com/adolfo/binder/c01.htm#k1-micro-eficiencia
00405 */
00406 
00407 /** Obtiene el hermano no vacío anterior, que está hacia la izquierda.
00408     - Si no existe un hermano no vacío hacia la izquierda, retorna un sub-árbol vacío.
00409     - Si <code>n == Child_Number()</code> no necesariamente ocurrirá que
00410       <code> (n-1)== Left_Sibling().Child_Number()</code>
00411       pues los anteriores hijos de \c Father() pueden ser sub-árboles vacíos, como ocurre si
00412       un árbol binario tiene hijo derecho pero no tiene hijo izquierdo.
00413     - Este método usualmente se usa junto con \c Rightmost()
00414 
00415     \par Complejidad:
00416          O( <code> Father().Count_Children() </code> ) */
00417 template <class E>
00418 Tree<E> Tree<E>::Left_Sibling() const {
00419     if (m_root == 0)  {
00420         return Tree( );
00421     }
00422     if (m_root->m_father == 0)  {
00423         return Tree( );
00424     }
00425 
00426     unsigned i = m_root->m_n_child;
00427     for (;;) {
00428         if (i == 0) { // tanto enredo para usar "unsigned" en lugar de "int"
00429             break;
00430         }
00431         --i;
00432         if (m_root->m_father->m_Lchild[i] != 0) {
00433             return Tree( (NOT_null_pointer*) m_root->m_father->m_Lchild[i] );
00434         }
00435     }
00436     return Tree( ); // ya no hay más hermanos
00437 }
00438 
00439 /** Obtiene el hermano no vacío siguiente, que está hacia la derecha.
00440     - Si no existe un hermano hacia la derecha, retorna un sub-árbol vacío.
00441     - Si <code>n == Child_Number()</code> no necesariamente ocurrirá que
00442       <code>(n+1) == Right_Sibling().Child_Number()</code>
00443       pues los siguientes hijos de \c Father() pueden ser sub-árboles vacíos, como ocurre si
00444       un árbol binario tiene hijo izquierdo pero no tiene hijo derecho.
00445     - Este método usualmente se usa junto con \c Leftmost()
00446 
00447     \par Complejidad:
00448          O( <code> Father().Count_Children() </code> ) */
00449 template <class E>
00450 Tree<E> Tree<E>::Right_Sibling() const {
00451     if (m_root == 0)  {
00452         return Tree( );
00453     }
00454     if (m_root->m_father == 0) {
00455         return Tree( );
00456     }
00457     for (unsigned i = m_root->m_n_child + 1; i<N; ++i) { // comienza en el hermano derecho
00458         if ( m_root->m_father->m_Lchild[i] != 0) {
00459             return Tree ( (NOT_null_pointer*) m_root->m_father->m_Lchild[i] );
00460         }
00461     }
00462     return Tree( ); // ya no hay más hermanos
00463 }
00464 
00465 /** Obtiene el hermano que está inmediatamente hacia la izquierda.
00466     - Este método es equivalente a invocar \c Sibling( -1 )
00467     - Si no existe un hermano hacia la derecha, retorna un sub-árbol vacío.
00468 
00469     \par Complejidad:
00470          O( \c 1 ) */
00471 template <class E>
00472 Tree<E> Tree<E>::Left_Sibling_Inmediate() const {
00473     if (m_root == 0)  {
00474         return Tree( );
00475     }
00476     if (m_root->m_father == 0)  {
00477         return Tree( );
00478     }
00479     unsigned nplus = 1 + m_root->m_n_child;
00480     if ( m_root->m_n_child == 0 ) {
00481         return Tree( );
00482     } else {
00483         return Tree ( m_root->m_father->m_Lchild[ m_root->m_n_child - 1 ] );
00484     }
00485 }
00486 
00487 /** Obtiene el hermano que está inmediatamente hacia la derecha.
00488     - Este método es equivalente a invocar \c Sibling( +1 )
00489     - Si no existe ese hermano hacia la derecha, retorna un sub-árbol vacío.
00490 
00491     \par Complejidad:
00492          O( \c 1 ) */
00493 template <class E>
00494 Tree<E> Tree<E>::Right_Sibling_Inmediate() const {
00495     if (m_root == 0)  {
00496         return Tree( );
00497     }
00498     if (m_root->m_father == 0)  {
00499         return Tree( );
00500     }
00501     unsigned nplus = 1 + m_root->m_n_child;
00502     if ( nplus == N ) {
00503         return Tree( );
00504     } else {
00505         return Tree ( m_root->m_father->m_Lchild[nplus] );
00506     }
00507 }
00508 
00509 /** \c "n"-ésimo hermano a partir de \c "*this".
00510     - El hermano puede ser vacío aunque haya otros hermanos que no son vacíos.
00511     - Se "corre" hacia el n-ésimo hermano \c "n" "posiciones".
00512     - El hermano se determina contando sub-árboles hacia la derecha o izquierda de acuerdo
00513       al signo de \c "n":
00514           - Si \c n=0, regresa \c "*this".
00515           - Si \c n>0, regresa el hermano número \c "+n" contando hacia la derecha de \c "*this".
00516           - Si \c n<0, regresa el hermano número \c "-n" contando hacia la izquierda de \c "*this".
00517     - Si no existe un hermano número \c "n" retorna un sub-árbol vacío.
00518     - El árbol \c "T" tiene 3 hijos no vacíos \c "B", \c "C" y \c "E" y tiene 4 sub-árboles:
00519             - <code> C.Sibling( +0 ) == C</code>
00520             - <code> B.Sibling( +1 ) == C</code>
00521             - <code> E.Sibling( -2 ) == C</code>
00522             - <code> E.Sibling( -1 ) --> Vacío</code>
00523             - <code> A.Sibling( +1 ) --> Vacío </code>
00524             - <code> B.Sibling( -1 ) --> Vacío </code>
00525             - <code> E.Sibling( +1 ) --> Vacío </code>
00526         \code
00527            A <-- T
00528           /|\
00529         / / \ \       [] --> es representa un sub-árbol vacío
00530        B C  [] E
00531         \endcode
00532 
00533     \par Complejidad:
00534          O( <code> Father().Count_Children() </code> ) */
00535 template <class E>
00536 Tree<E> Tree<E>::Sibling( int n ) const {
00537     if (m_root == 0)  {
00538         return Tree( );
00539     }
00540     if ( n==0 ) {
00541         return Tree( (NOT_null_pointer*) m_root );
00542     }
00543     if (m_root->m_father == 0)  {
00544         return Tree( );
00545     }
00546 
00547     if ( n >= 0 ) {
00548         unsigned n_new = n + m_root->m_n_child;
00549         if (n_new < Tree<E>::N) {
00550             return Tree( m_root->m_father->m_Lchild[n_new] );
00551         } else {
00552             return Tree( );
00553         }
00554     } else {
00555         int n_abs = -n;
00556         if ( m_root->m_n_child >= n_abs ) { // se puede hacer la resta
00557             return Tree( m_root->m_father->m_Lchild[ m_root->m_n_child - n_abs ] );
00558         } else {
00559             return Tree( );
00560         }
00561     }
00562 }
00563 
00564 /** Obtiene el hijo más izquierdo del árbol.
00565     - Este método usualmente se usa junto con \c Right_Sibling()
00566 
00567     \par Complejidad:
00568          O( <code> Count_Children() </code> )
00569 
00570     \remark Esta es una forma de procesar los hijos no vacíos de un sub-árbol de izquierda a derecha:
00571 
00572     \code
00573     Tree<E> Child = T.Leftmost();
00574     while ( ! Child.Empty() ) {
00575         Process( Child );
00576         Child = Child.Right_Sibling();
00577     }
00578     \endcode */
00579 template <class E>
00580 Tree<E> Tree<E>::Leftmost() const {
00581     if (m_root == 0)  {
00582         return Tree( );
00583     }
00584     for (unsigned i=0; i<N; ++i) {
00585         if ( m_root->m_Lchild[i] != 0) {
00586             return Tree ( (NOT_null_pointer*) m_root->m_Lchild[i] );
00587         }
00588     }
00589     return Tree( ); // ==> m_root == 0
00590 }
00591 
00592 /** Obtiene el hijo más derecho del árbol.
00593     - Este método usualmente se usa junto con \c Left_Sibling()
00594     - Requiere O(n) tiempo de ejecución, donde \c "n" es la cantidad de hijos de \c "*this"
00595 
00596    \remark Esta es una forma de procesar los hijos no vacíos de un sub-árbol de derecha a izquierda:
00597 
00598    \code
00599     Tree<E> Child = T.Rightmost();
00600     while ( ! Child.Empty() ) {
00601         Process( Child );
00602         Child = Child.Left_Sibling();
00603     }
00604    \endcode */
00605 template <class E>
00606 Tree<E> Tree<E>::Rightmost() const {
00607     if (m_root == 0)  {
00608         return Tree( );
00609     }
00610 
00611     unsigned i = N;
00612     for (;;) {
00613         if (i == 0) { // tanto enredo ... para usar "unsigned" en lugar de "int"
00614             break;
00615         }
00616         --i;
00617         if (m_root->m_Lchild[i] != 0) {
00618             return Tree( (NOT_null_pointer*) m_root->m_Lchild[i] );
00619         }
00620     }
00621     return Tree( ); // ==> m_root == 0
00622 }
00623 
00624 /** Implementación recursiva para \c Count().
00625     - Incrementa \c "n" en el número de hijos que tiene el sub-árbol cuya raíz es \c "p"
00626     - Cambia el valor de \c "n"
00627     - No cuenta el nodo raíz \c "p"
00628     - Esta función complementa a \c Count()
00629 
00630     \pre p != 0 */
00631 template <class E>
00632 void Tree<E>::Count0(const Tree_Node<E> * p, unsigned & n) {
00633     for (unsigned i=0; i < N; ++i) {
00634         if (p->m_Lchild[i] != 0) {
00635             ++n; // cuenta a este hijo
00636             Count0( p->m_Lchild[i], n );
00637         }
00638     }
00639 }
00640 
00641 /** Retorna la cantidad de valores almacenados en el sub-árbol.
00642     - Calcula el número de sub-árboles no vacíos del árbol
00643 
00644     \par Complejidad:
00645          O( \c Count() ) ==> tiempo <br>
00646          O( \c Height() ) ==> espacio
00647 
00648     \see http://www.di-mare.com/adolfo/binder/c05.htm#sc03 */
00649 template <class E>
00650 unsigned Tree<E>::Count() const {
00651     if (m_root == 0) {
00652         return 0;
00653     } else {
00654         unsigned n = 1; // comienza contando en uno...
00655         Count0(m_root, n); // ... porque Count0() no cuenta la raíz
00656         return n;
00657     }
00658 }
00659 
00660 /** Retorna la cantidad de hijos del árbol.
00661     \par Complejidad:
00662          O( \c Count_Children() ) */
00663 template <class E>
00664 unsigned Tree<E>::Count_Children() const {
00665     unsigned tot = 0;
00666     for (unsigned i=0; i < N; ++i) {
00667         if (m_root->m_Lchild[i] != 0) {
00668             ++tot; // cuenta a este hijo porque no está vacío
00669         }
00670     }
00671     return tot;
00672 }
00673 template <class E>
00674 inline bool operator == (const Tree<E> &p, const Tree<E> &q) { return Tree<E>::Comp0(p.m_root, q.m_root); }
00675 template <class E>
00676 inline bool operator != (const Tree<E> &p, const Tree<E> &q) { return !(p == q); }
00677 
00678 /** Compara recursivamente los árboles cuyos nodo raíz son \c "*p" y \c "*q".
00679     - Implementación recursiva para <code> operator==(Tree, Tree) </code> */
00680 template <class E>
00681 bool Tree<E>::Comp0(const Tree_Node<E> *p, const Tree_Node<E> *q) {
00682     if (p == q) {
00683         return true;
00684     }
00685     if ( (p==0) || (q == 0)) { // son diferentes...
00686         return false; // ...pues sólo 1 está vácio
00687     }
00688     if ( ! (p->m_data == q->m_data) ) {
00689         return false; // valor diferente en la raíz
00690     }
00691 
00692     // A comparar a todos los hijos
00693     for (unsigned i=0; i < Tree<E>::N; ++i) {
00694         if (! Comp0(p->m_Lchild[i], q->m_Lchild[i]) ) {
00695             return false;
00696         }
00697     }
00698 
00699     return true; // pues nunca encontró nodos diferentes
00700 }
00701 
00702 /**   Verifica que se cumpla la invariante de la clase, o sea, que el objeto esté bien construido.
00703       - La razón por la que esta función no es un método es continuar la costumbre de muchos
00704         programadores quienes no definen la invariante para sus clases, pues en muchos
00705         casos sobra hacerlo.
00706       - No invoca \c check_ok( value_type& ) para cada valor almacenado, aunque si el árbol
00707         cumple con su invariante necesariamentes es porque también sus elementos almacenados
00708         están bien construidos.
00709       - Esta función en general es difícil de implementar, y en algunos casos es imposible
00710         pues, cuando el objeto no está bien construido, puede ocurrir que la función no
00711         retorne (como ocurriria si un nodo interno del árbol apunta de vuelta a la raíz, lo
00712         que se resulta en un círculo).
00713       - En general, la implementáción de esta función no es completa pues hay casos en que
00714         es imposible verificar la invariante de una clase.
00715 
00716     \par Complejidad:
00717          O( \c Count() ) ==> tiempo <br>
00718          O( \c Height() ) ==> espacio
00719 
00720          \post Retorna \c "true" si el árbol es un objeto bien construido
00721       \see \c check_ok(Tree&)
00722 
00723     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc11 */
00724 template <class E>
00725 bool check_ok(const Tree<E>& T) {
00726 
00727     if ( T.Empty() ) {
00728         return true;
00729     }
00730 
00731     #ifdef NO_Implementado_para_evitar_forzar_que_el_valor_almacenado_tenga_su_metodo_OK
00732         if (! check_ok( T.Data() ) ) { // si el valor almacenado no esta bien...
00733             return false; //... tampoco lo está el árbol
00734         }
00735         /* Usar la función check_ok(Tree<E>::value_type en lugar del método
00736         Tree<E>::value_type::Ok() evitar forzar a que los programadores clientes
00737         que usen árboles estén obligados a implementar el método
00738         Tree<E>::value_type::Ok(), que se encarga de verificar la invariante del valor
00739         almacenado en le árbol.
00740         - Lindo: if (! check_ok( T.Data() ) ) //.... la función check_ok() es opcional
00741         - ¡FEO!: if (! T.Data().Ok() ) //... pues obliga a que exista el método value_type::Ok()
00742         */
00743     #endif
00744 
00745     for (unsigned i = 0; i < Tree<E>::N; ++i) {
00746         if ( T.Child(i).Empty() ) { // este hijo no existe
00747             // continue; // con el siguiente
00748         }
00749         else if ( T.Child(i).Father() != T.Root() ) { // ==> ! T.Father.Empty()
00750             return false; // parece que este hijo no es mi hijo...
00751         }
00752         else if ( i != T.Child(i).Child_Number() ) {
00753             return false; // no estoy registrado como el i-ésimo hijo de mi padre
00754         }
00755         else if ( T.Child(i).Father().Child( i ) != T.Child( i ) ) {
00756             return false; // no estoy registrado como el i-ésimo hijo de mi padre
00757         }
00758         else if ( ! check_ok( T.Child(i) ) ) {
00759             return false; // hijo roto...
00760         }
00761     }
00762     return true;
00763 
00764     // Las siguientes relaciones lógicas se cumplen
00765     // [ ! T.Empty() ]                    ==> [ T.Root()!= Tree() ]
00766     // [ T.Child(i).Father() == T.Root()] ==> [ ! T.Father.Empty() ]
00767 
00768     /* Si este método retorna es porque el árbol está bien construido. Sin embargo,
00769        una invocación a check_ok() con un árbol mal construido posiblemente nunca retorne.
00770     */
00771 }
00772 
00773 /**  Sustituye por \c "d" el valor almacenado en la raíz del árbol.
00774     - Si el árbol está vacío, le agrega el nodo raíz.
00775 
00776     \returns \c *this */
00777 template <class E>
00778 Tree<E> Tree<E>::Change_Root(const value_type & d) {
00779     if (m_root == 0) { // como el árbol está vacío hay que agregarle la raíz
00780         m_root = Tree_Node<E>::Get_New(d); // crea el nodo raíz
00781         m_root->No_Children(); // y le pone en blanco todos sus hijos
00782     } else { // como no hay más referencias....
00783         m_root->m_data = d; // ... cambia el valor directamente
00784     }
00785     return *this;
00786 }
00787 
00788 /** Sustituye por \c "d" el valor almacenado en el hijo número \c "n" del árbol.
00789     - Si no existe el hijo número \c "n", lo agrega como una hoja con valor \c "d"
00790     - Si ya existe el hijo número \c "n", le sustituye su valor por \c "d"
00791 
00792     \pre <code> !Empty() && (0 <= n) && (n < Tree<E>::N) </code>
00793 
00794     \par Complejidad:
00795          O( \c Count_Children() )
00796 
00797     \returns <code> Child(n) </code> */
00798 template <class E>
00799 Tree<E> Tree<E>::Change_Child(unsigned n, const value_type &d) {
00800     if (m_root == 0) { // ignora árboles vacíos
00801         return Tree( );
00802     }
00803     if (n >= Tree<E>::N) { // ignora índices fuera de rango
00804         return Tree( );
00805     }
00806     if (m_root->m_Lchild[n] == 0) { // Hay que agregar un sub-árbol nuevo
00807         Tree_Node<E> * p = Tree_Node<E>::Get_New(d);
00808         p->No_Children();
00809         p->m_father = m_root;
00810         p->m_n_child = n;
00811         m_root->m_Lchild[n] = p;
00812     } else {
00813         m_root->m_Lchild[n]->m_data = d; // cambia el valor directamente
00814     }
00815     return Tree( (NOT_null_pointer*) m_root->m_Lchild[n] );
00816 }
00817 
00818 /** Sustituye por \c "d" el valor almacenado en el hermano inmediatamente anterior del sub-árbol.
00819     - Si <code> n == Child_Number() </code> cambia el valor
00820       del hijo número \c "n-1" de \c Father()
00821     - Si no existe el hijo número \c "n-1" de \c Father() lo agrega como
00822       una hoja con valor \c "d"
00823     - Si ya existe ese hijo número \c "n-1", le sustituye su valor por \c "d"
00824     - Retorna un árbol vacío si no es posible que exista el hijo número \c "n-1" de \c Father()
00825 
00826     \pre <code> !Empty() && (1 <= Child_Number()) </code>
00827 
00828     \par Complejidad:
00829          O( \c 1 )
00830 
00831     \returns El hermano izquierdo, <code> Sibling(-1) </code> */
00832 template <class E>
00833 Tree<E> Tree<E>::Change_Left_Sibling_Inmediate( const value_type &d ) {
00834     if (m_root == 0) { // ignora árboles vacíos
00835         return Tree( );
00836     }
00837     unsigned n = m_root->m_n_child;
00838     if ( n == 0 ) { // no hay hijos hacia la izquierda
00839         return Tree( );
00840     }
00841     // assert( (m_root->m_n_child > 0) && (n > 0) );
00842     n--;
00843     if (m_root->m_father->m_Lchild[ n ] == 0) { // Hay que agregar un sub-árbol nuevo
00844         Tree_Node<E> * p = Tree_Node<E>::Get_New(d);
00845         p->No_Children();
00846         p->m_father = m_root->m_father;
00847         p->m_n_child = n;
00848         m_root->m_father->m_Lchild[ n ]->m_data = d;
00849     } else {
00850         m_root->m_father->m_Lchild[ n ]->m_data = d; // cambia el valor directamente
00851     }
00852     return Tree( (NOT_null_pointer*) m_root->m_Lchild[n] );
00853 }
00854 
00855 /** Sustituye por \c "d" el valor almacenado en el hermano inmediatamente posterior del sub-árbol.
00856     - Si <code> n == Child_Number() </code> cambia el valor
00857       del hijo número \c "n+1" de \c Father()
00858     - Si no existe el hijo número \c "n+1" de \c Father() lo agrega como
00859       una hoja con valor \c "d"
00860     - Si ya existe ese hijo número \c "n+1", le sustituye su valor por \c "d"
00861     - Retorna un árbol vacío si no es posible que exista el hijo número \c "n+1" de \c Father()
00862 
00863     \pre <code> !Empty() && ( Child_Number() < Tree<E>::N ) </code>
00864 
00865     \par Complejidad:
00866          O( \c 1 )
00867 
00868     \returns El hermano derecho, <code> Sibling(+1) </code> */
00869 template <class E>
00870 Tree<E> Tree<E>::Change_Right_Sibling_Inmediate( const value_type &d ) {
00871     if (m_root == 0) { // ignora árboles vacíos
00872         return Tree( );
00873     }
00874     unsigned n = m_root->m_n_child + 1;
00875     if (n >= Tree<E>::N) { // no hay hijos hacia la derecha
00876         return Tree( );
00877     }
00878     // assert( n < Tree<E>::N );
00879     if (m_root->m_father->m_Lchild[ n ] == 0) { // Hay que agregar un sub-árbol nuevo
00880         Tree_Node<E> * p = Tree_Node<E>::Get_New(d);
00881         p->No_Children();
00882         p->m_father = m_root->m_father;
00883         p->m_n_child = n;
00884         m_root->m_father->m_Lchild[ n ]->m_data = d;
00885     } else {
00886         m_root->m_father->m_Lchild[ n ]->m_data = d; // cambia el valor directamente
00887     }
00888     return Tree ( m_root->m_Lchild[n] );
00889 }
00890 
00891 /** Elimina recursivamente a \c "*p" y a todos sus descendientes.
00892     - Implementación recursiva para \c Erase()
00893     - Borra el nodo sólo después de que constata que ya no hay punteros que le apunten
00894     - No actualiza los punteros en el padre ==> ese es el trabajo de \c Graft() o \c Erase()
00895     - Lo que sí hace es decrementar \c "p->m_refCount"
00896     - Recursivamente, borra a los descendientes de \c "*p"
00897 
00898     \pre <code> p != 0 </code>
00899     \post No cambia \c "p" porque trabaja con una copia de su valor */
00900 template <class E>
00901 void Tree<E>::Erase0( Tree_Node<E> * p ) {
00902     // assert( p != 0 );
00903     p->m_refCount--; // ya "p" no apunta al nodo
00904     if (p->m_refCount == 0) { // elimina el nodo ==> esta es la última referencia
00905         // A matar hijos...
00906         for (unsigned i = 0; i < N; i++) {
00907             Tree_Node<E> * q = p->m_Lchild[i];
00908             if (q != 0) {
00909                 if (q->m_father == p) { // lo des-padre-ja...
00910                     q->m_father = 0; // ... pues ya "p" no es su padre
00911                 }
00912                 Erase0(q); // elimina recursivamente a cada uno de sus hijos
00913             }
00914             // Esta sobra porque "*p" va a desaparecer
00915             // p->m_Lchild[i] = 0; // ya ese nodo no es hijo de nadie
00916         }
00917         #ifdef USE_v_Alive
00918             // Elimina a "p" de m_v_Alive[]
00919             for (unsigned j = 0; j < Tree_Node<E>::N_Alive; ++j) {
00920                 if (p == Tree_Node<E>::m_v_Alive[j]) { // busca hasta que encuentra al puntero
00921                     break;
00922                 }
00923             }
00924             if (j < Tree_Node<E>::N_Alive) { // sí lo encontró
00925                 for (unsigned k = j; k < Tree_Node<E>::N_Alive; ++k) { // corre a los demás para atrás
00926                     Tree_Node<E>::m_v_Alive[k] = Tree_Node<E>::m_v_Alive[k+1];
00927                 }
00928                 Tree_Node<E>::m_n_Alive--; // ahora hay uno menos
00929             } else {
00930                 for (unsigned k = 0; k<3; ++j) { // marca "feos" los del final
00931                     Tree_Node<E>::m_v_Alive[Tree_Node<E>::N_Alive-1-k] = (Tree_Node<E> *)(-1);
00932                 }
00933             }
00934         #endif
00935         delete p; // ... lo mata sólo si esta es la última referencia
00936     }
00937 }
00938 
00939 /** Elimina el árbol y sus descendientes.
00940     \par Complejidad:
00941          O( \c Count() ) + O( <code> Father().Count() </code> ) ==> tiempo <br>
00942          O( \c Height() ) ==> espacio
00943 
00944     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc03 */
00945 template <class E>
00946 void Tree<E>::Erase() {
00947     if (m_root == 0) {
00948         return;
00949     } else if (m_root->m_father != 0) {
00950         m_root->m_father->m_Lchild[m_root->m_n_child] = 0;
00951     }
00952     Erase0(m_root);
00953     m_root = 0;
00954 }
00955 
00956 // Esta documentación para Tree<E>::Erase_Son() aparece acá porque Doxygen no permite
00957 // incluir un párrafo aparte "\par" en la documentación de 1 sólo renglón.
00958 
00959 /** \fn void Tree<E>::Erase_Son(unsigned n)
00960 
00961     \brief Elimina el sub-árbol número \c "n"
00962 
00963     \par Complejidad:
00964          O( <code> Child(n).Count() </code> ) ==> tiempo <br>
00965          O( <code> Height( Child(n) )  </code> ) ==> espacio
00966 */
00967 
00968 /**   Verifica que se cumpla la invariante de la clase, o sea, que el objeto esté bien construido.
00969       - Además de todo el trabajo que hace \c check_ok(Tree& T), acá hay que constatar que
00970         el nodo raíz no tiene padre, que es la diferencia fundamental entre un árbol y un sub-árbol
00971 
00972       \post Retorna \c "true" si el árbol es un objeto bien construido
00973 
00974       \deprecated Los árboles y los sub-árboles son la misma cosa.
00975 
00976       \see \c check_ok(Tree&) */
00977 template <class E>
00978 inline bool check_ok_Tree(const Tree<E>& T) {
00979     if ( T.Root().Empty() ) {
00980         return true;
00981     } else {
00982         return ( T.Root().Father().Empty() ) && check_ok( Tree<E>(T) );
00983     }
00984 }
00985 
00986 /** Hace una copia profunda nodo por nodo del árbol cuyo nodo raíz es \c "*p".
00987     - Implementación recursiva para \c Tree<E>::Copy_Deep()
00988     - No altera \c p->m_refCount porque copia los nodos.
00989     - \c "father" indica quién debe ser el padre del nuevo nodo
00990     - \c "father" no es el padre de \c "*p"
00991 
00992     \pre <code> p != 0 </code>
00993     \post No cambia \c "p" porque trabaja con una copia de su valor
00994 
00995     \returns Puntero al nodo raíz del árbol copiado */
00996 template <class E>
00997 Tree_Node<E> * Tree<E>::Copy_Deep0(Tree_Node<E> * father, const Tree_Node<E> * p) {
00998     Tree_Node<E> * q; // resultado
00999     q = Tree_Node<E>::Get_New(p->m_data); // m_refCount = 1; m_n_child = 0; m_father = 0;
01000     q->m_n_child = p->m_n_child;
01001     q->m_father = father;
01002 
01003     // inicializa los punteros a los hijos que estarán en m_Lchild[]
01004     for (unsigned i=0; i < N; ++i) {
01005         if (p->m_Lchild[i] == 0) { // si en el árbol fuente este hijo no existe...
01006             q->m_Lchild[i]  = 0; // ...tampoco existirá en la copia
01007         } else { // copie todo el sub-árbol
01008             q->m_Lchild[i] = Copy_Deep0(q, p->m_Lchild[i]);
01009         }
01010     }
01011     return q;
01012 }
01013 
01014 /** Copia profunda de \c "o".
01015     - Copia todo el valor de \c "o" sobre \c "*this", de forma que el nuevo valor de
01016       \c "*this" sea un duplicado exacto del valor de \c "o"
01017     - El valor anterior de \c "*this" se pierde
01018     - El objeto \c "o" mantiene su valor anterior
01019     - Luego de la copia, cuando el valor de \c "o" cambia, el de \c "*this" no cambiará,
01020       y viceversa, pues la copia es una copia profunda; no es superficial
01021     - Si \c "*this" es \c "o" entonces su valor no cambia
01022     - Después de esta operación siempre ocurre que <code> *this == o </code>
01023 
01024     \par Complejidad:
01025          O( \c Count() ) + O( \c o.Count() )
01026 
01027   \returns \c *this
01028 
01029     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05 */
01030 template <class E>
01031 Tree<E>& Tree<E>::Copy_Deep(const Tree &o) {
01032     if (m_root != 0) {
01033         Erase0(m_root);  // Borra el contenido actual del árbol
01034     }
01035     if (o.m_root != 0 ) {
01036         m_root = Copy_Deep0(0, o.m_root); // 0 == cero == this->Father()
01037     } else {
01038         m_root = 0;
01039     }
01040     return *this;
01041 }
01042 
01043 /** Injerta \c "o" para que sea el \c "n"-ésimo hijo de \c "*this".
01044     - Si \c "o" es sub-árbol de otro árbol, dejara de serlo para pasar ser hijo de \c "*this"
01045     - Si \c "*this" tiene un \c "n"-ésimo hijo, ese hijo desaparece
01046     - Si \c "o" está vacío, elimina el \c "n"-ésimo hijo del árbol [<code> Erase_Son(n) </code>]
01047 
01048     \pre
01049     - <code> ! Root().Empty() </code>
01050        - Si el  árbol está vacío no tiene raíz, y por lo tanto tampoco puede tener hijos
01051     - <code> ! Ancestor(o, *this) </code>
01052        - "o" no puede ser ancestro de *this"
01053     - <code> (0 <= n) && (n < Tree<E>::N) </code>
01054     - <code> ! Root(). Same( o.Root() ) </code>
01055 
01056     \post
01057     - \c "o" deja de ser sub-árbol del árbol en que estaba
01058     - <code> o.Father() .Same( Root() ) </code>
01059 
01060     \remarks
01061     - Un sub-árbol puede ser hijo (o sub-árbol) de otro árbol
01062     - Un sub-árbol puede ser hijo únicamente de un árbol
01063     - Este método no hace nada cuando [ <code> ! Root() .Same( o.Root() ) </code> ]
01064     - Injertar un sub-árbol vacío es una forma de eliminar a un hijo junto con
01065       toda su descendencia
01066 
01067     \returns "o" ==> El árbol recién injertado
01068 
01069     \par Complejidad::
01070          O( \c Count_Children() ) + O( <code> o.Father().Count_Children() </code> ) */
01071 template <class E>
01072 Tree<E> Tree<E>::Graft(unsigned n, Tree &o) {
01073     if (m_root == 0) { // ignora árboles vacíos
01074         return Tree( );
01075     }
01076     if (m_root == o.m_root) { // evita auto-borrado
01077         return Tree( (NOT_null_pointer*) m_root );
01078     }
01079     #ifdef FALTA_verificar_en_Graft
01080         bool Ancestor( Tree & Child, Tree & Father );
01081         assert( ! Ancestor( o, *this ) ); // "o" no puede ser ancestro de *this"
01082     #endif
01083     if (n >= Tree<E>::N) { // ignora punteros nulos
01084         return Tree( (NOT_null_pointer*) m_root );
01085     }
01086     if (m_root->m_Lchild[n] == o.m_root) { // ya el hijo está ahí
01087         return Tree( (NOT_null_pointer*) m_root );
01088     }
01089     if (m_root->m_Lchild[n] != 0) {
01090         m_root->m_Lchild[n]->m_father = 0; // deja a este hijo [n] sin padre aunque...
01091         m_root->m_Lchild[n]->m_n_child = 0; // ...puede que haya otras referencias a este mismo nodo
01092         Erase0( m_root->m_Lchild[n] ); // elimna el n-ésimo hijo de "*this"
01093     }
01094     if (o.m_root == 0) {
01095         m_root->m_Lchild[n] = 0; // Caso trival si el árbol "o" a injertar está vacío
01096     } else {
01097         if (o.m_root->m_father != 0) { // desliga al hijo "o" de su padre actual
01098             o.m_root->m_father->m_Lchild[o.m_root->m_n_child] = 0; // ya no es hijo del padre anterior
01099             o.m_root->m_refCount--; // pues dejó de ser hijo del padre anterior
01100         }
01101         o.m_root->m_father = m_root; // nuevo padre
01102         o.m_root->m_n_child = n; // coloca a "o" como el "n-ésimo" hijo
01103         o.m_root->m_refCount++; // su nuevo padre ahora ya le apunta
01104         m_root->m_Lchild[n] = o.m_root;
01105     }
01106 
01107     return Tree( m_root->m_Lchild[n] );
01108 } // Tree<E>::Graft()
01109 
01110 } // namespace TV
01111 
01112 #endif  // Tree_V_h
01113 
01114 // EOF: Tree_V.h

Generado el Tue Jun 30 06:20:32 2009 para Uso de TL::Tree y TV::Tree: por  doxygen 1.3.9.1