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