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

Generado el Sun Feb 19 09:37:34 2006 para Uso de TL::Tree y TV::Tree: por  doxygen 1.3.9.1