#include <Bin_Tree.h>
Constructores y destructor | |
| Bin_Tree () | |
| Constructor de vector: el árbol queda vacío. | |
| Bin_Tree (const Bin_Tree &other) | |
| Constructor de copia: los dos árboles comparten la misma raíz. | |
| Bin_Tree (const value_type &d) | |
| Constructor a partir de un valor. | |
| ~Bin_Tree () | |
| Destructor. | |
| Bin_Tree (lkptr< Bin_Tree_Node< E > > &other) | |
| Constructor a partir de un puntero a un nodo. | |
| Bin_Tree (const lkptr< Bin_Tree_Node< E > > &other) | |
Constructor a partir de un puntero a un nodo (puntero const). | |
Operaciones básicas | |
| bool | isEmpty () const |
Retorna "true" si el sub-árbol está vacío. | |
| unsigned | count () const |
| Retorna la cantidad de valores almacenados en el sub-árbol. | |
| unsigned | countChildren () const |
| Retorna la cantidad de hijos del árbol. | |
| unsigned | size () const |
Usa count() para retornar la cantidad de valores almacenados en el sub-árbol. | |
| bool | ok () const |
Verifica la invariante de Bin_Tree<E>. | |
| template<class T> | |
| bool | check_ok (const Bin_Tree< T > &aT) |
Usa ok() para verificar la invariante de la clase. | |
Operaciones de comparación | |
| bool | equals (const Bin_Tree &o) const |
| ¿¿¿ (*this==o) ??? | |
| bool | same (const Bin_Tree &o) const |
Retorna true si "o" comparte la raíz con "*this". | |
| template<class T> | |
| bool | operator== (const Bin_Tree< T > &p, const Bin_Tree< T > &q) |
| ¿¿¿ (p == q) ??? | |
| template<class T> | |
| bool | operator!= (const Bin_Tree< T > &p, const Bin_Tree< T > &q) |
| ¿¿¿ (p != q) ??? | |
Public Types | |
| typedef E | value_type |
| Nombre estándar del tipo de elemento contenido. | |
| typedef const value_type & | const_reference |
| Referencia constante al objeto contenido. | |
| typedef unsigned | size_type |
Nombre estándar del tipo retornado por size(). | |
Public Member Functions | |
Operaciones de borrado | |
| void | erase () |
| Deja el árbol vacío. | |
| void | clear () |
Sinónimo de erase(). | |
Operaciones de copiado | |
| Bin_Tree & | operator= (const Bin_Tree &other) |
Sinónimo de this->copy(o) (pero retorna *this). | |
| void | copy (const Bin_Tree &other) |
Copia superficial desde "o". | |
| Bin_Tree & | operator= (const value_type &d) |
Usa changeRoot() para sustituir por "d" el valor almacenado en la raíz del árbol. | |
| void | move (Bin_Tree &other) |
Traslada a "*this" el valor de "other". | |
| void | swap (Bin_Tree &other) |
Intercambia los valores de "*this" y "o". | |
Métodos para cambiar los valores almacenados en el árbol | |
| void | changeRoot (const value_type &d) |
Sustituye por "d" el valor almacenado en la raíz del árbol. | |
| void | changeLeftChild (const value_type &d) |
Sustituye por "d" el valor almacenado en el hijo izquierdo del árbol. | |
| void | changeRightChild (const value_type &d) |
Sustituye por "d" el valor almacenado en el hijo derecho del árbol. | |
| void | makeLeftChild (Bin_Tree T) |
Pone al árbol "T" como sub-árbol izquierdo de "*this". | |
| void | makeRightChild (Bin_Tree T) |
Pone al árbol "T" como sub-árbol derecho de "*this". | |
| void | releaseLeftChild () |
| Elimina el hijo izquierdo del árbol. | |
| void | releaseRightChild () |
| Elimina el hijo derecho del árbol. | |
| void | makeOrphan () |
| Desconecta al hijo del padre. | |
Operaciones para usar los valores almacenados | |
| value_type & | data () const |
| Valor almacenado en la raíz del sub-árbol. | |
| value_type & | operator* () const |
| Valor almacenado en la raíz del sub-árbol. | |
| value_type * | operator-> () const |
| Puntero al valor almacenado en la raíz del sub-árbol. | |
Métodos para recorrer el árbol | |
| const Bin_Tree | root () const |
| Raíz del sub-árbol. | |
| Bin_Tree | father () const |
| Acceso al padre. | |
| Bin_Tree | left () const |
| Acceso al hijo izquierdo. | |
| Bin_Tree | right () const |
| Acceso al hijo derecho. | |
| Bin_Tree | child (int i) const |
| Acceso al i-ésimo hijo del árbol. | |
Propiedades del árbol | |
| bool | isRoot () const |
Retorna "true" si el árbol no tiene padre. | |
| bool | isLeaf () const |
Retorna "true" si el árbol es una hoja. | |
| bool | isLeftChild () const |
Retorna "true" si el árbol es el hijo izquierdo de su padre. | |
| bool | isRightChild () const |
Retorna "true" si el árbol es el hijo derecho de su padre. | |
| unsigned | use_count () const |
| Cantidad de referencias de la raíz del árbol. | |
Private Attributes | |
| lkptr< Bin_Tree_Node< E > > | m_root |
| Un árbol "es" el puntero al nodo raíz. | |
copyDeep().
{{ // test::multi_child()
// Muestra que un mismo árbol "Bebe" puede ser sub-árbol
// de varios árboles
Bin_Tree<E> Paco = E(); // Paco Lola //
Bin_Tree<E> Lola = E(); // //
Bin_Tree<E> Bebe; // E() E() //
Lola.makeLeftChild( E() ); // \\ / //
Bebe = Lola.left(); // Bebe //
Bebe.makeLeftChild( E() ); // // \\ //
Bebe.makeRightChild( E() ); // E() E() //
Paco.makeRightChild( Bebe );
// Como se muestra en el diagrama X, debido a este último cambio
// el padre registrado de Bebe ahora es Paco
assertTrue( 3 == Bebe.size() );
assertTrue( 4 == Paco.size() ); // 3 de Bebe + Paco
assertTrue( 4 == Lola.size() ); // 3 de Bebe + Lola
assertTrue( Paco.right().same( Bebe ) ); // Bebe es hijo de Paco
assertTrue( Lola.left() .same( Bebe ) ); // Bebe es hijo de Lola
assertTrue( Bebe.father().same( Paco ) ); // El papá de Bebe es Paco
assertTrue( ! Bebe.father().same( Lola ) ); // Lola no es ancestro de Bebe
// corrección: "Lola" no aparece registrada como padre para "Bebe"
Bebe.erase();
assertTrue( Bebe.isEmpty() ); // La referencia Bebe está vacía
Bebe = Lola.left(); // Se llega al hijo compartido desde Lola
assertTrue( ! Bebe.isEmpty() );
assertTrue( Bebe.father().same( Paco ) ); // Repito: el papá de Bebe es Paco
assertTrue( ! Bebe.father().same( Lola ) ); // Repito: Lola no es ancestro de Bebe
if ( false ) { // Tortón !!!
Bebe.left().makeRightChild( Paco ); // ciclo infinito en el árbol
Bebe.right().makeLeftChild( Lola );
}
}}
Definition at line 54 of file Bin_Tree.h.
| typedef E Bin_Tree< E >::value_type |
| typedef const value_type& Bin_Tree< E >::const_reference |
| template< class E > inline Bin_Tree< E >::Bin_Tree | ( | const Bin_Tree< E > & | o | ) | [inline] |
Constructor de copia: los dos árboles comparten la misma raíz.
1 ). Definition at line 68 of file Bin_Tree.h.
| Bin_Tree< E >::Bin_Tree | ( | const value_type & | d | ) | [inline] |
| Bin_Tree< E >::Bin_Tree | ( | lkptr< Bin_Tree_Node< E > > & | other | ) | [inline, private] |
| Bin_Tree< E >::Bin_Tree | ( | const lkptr< Bin_Tree_Node< E > > & | other | ) | [inline, private] |
Constructor a partir de un puntero a un nodo (puntero const).
Definition at line 75 of file Bin_Tree.h.
| bool Bin_Tree< E >::isEmpty | ( | ) | const [inline] |
| unsigned Bin_Tree< E >::count | ( | ) | const [inline] |
Retorna la cantidad de valores almacenados en el sub-árbol.
Definition at line 449 of file Bin_Tree.h.
| unsigned Bin_Tree< E >::countChildren | ( | ) | const [inline] |
Retorna la cantidad de hijos del árbol.
1 ) Definition at line 461 of file Bin_Tree.h.
| unsigned Bin_Tree< E >::size | ( | ) | const [inline] |
Usa count() para retornar la cantidad de valores almacenados en el sub-árbol.
Definition at line 86 of file Bin_Tree.h.
| bool Bin_Tree< E >::ok | ( | ) | const [inline] |
| void Bin_Tree< E >::erase | ( | ) | [inline] |
Deja el árbol vacío.
T.left().erase(); // No cambia "T" porque el que cambia es "T.left()" T.makeLeftChild( Bin_Tree<E>() ); // así sí se borra el hijo izquierdo T.makeRightChild( Bin_Tree<E>() ); // borra el hijo derecho
Definition at line 106 of file Bin_Tree.h.
| void Bin_Tree< E >::clear | ( | ) | [inline] |
Copia superficial desde "o".
"*this" se pierde.
1 ). Definition at line 365 of file Bin_Tree.h.
| Bin_Tree& Bin_Tree< E >::operator= | ( | const value_type & | d | ) | [inline] |
Usa changeRoot() para sustituir por "d" el valor almacenado en la raíz del árbol.
Definition at line 117 of file Bin_Tree.h.
Traslada a "*this" el valor de "other".
"*this" se pierde."*this" es el que "other" tuvo."other" queda en el estado en que lo dejaría other.erase()."*this" es "other" entonces su valor no cambia.this->equal(other) es "true".
count() ) {{ // test::move_swap()
Bin_Tree<E> Paco = E(), Lola = E(); // E() //
Paco.makeLeftChild( E() ); // / \ //
Paco.makeRightChild( E() ); // E() E() //
assertTrue( Paco.size() == 3 );
assertTrue( Lola.size() == 1 );
Paco.swap( Lola );
assertTrue( Paco.size() == 1 );
assertTrue( Lola.size() == 3 );
Lola.move( Paco );
assertTrue( Paco.size() == 0 );
assertTrue( Lola.size() == 1 );
}}
Definition at line 433 of file Bin_Tree.h.
Intercambia los valores de "*this" y "o".
"*this" en lugar de una referencia, como ocurre con Bin_Tree::child(), a veces swap() no tiene el resultado esperado por el programador. T.child(i). swap( T.child(j) ) el resultado no es intercambiar los hijos, sino más bien intercambiar los valores de los sub-árboles temporales T.child(i) y T.child(j). La forma correcta de intercambiar hijos es usar makeLeftChild() y/o makeRightChild().
1 ). {{ // test::move_swap()
Bin_Tree<E> Paco = E(), Lola = E(); // E() //
Paco.makeLeftChild( E() ); // / \ //
Paco.makeRightChild( E() ); // E() E() //
assertTrue( Paco.size() == 3 );
assertTrue( Lola.size() == 1 );
Paco.swap( Lola );
assertTrue( Paco.size() == 1 );
assertTrue( Lola.size() == 3 );
Lola.move( Paco );
assertTrue( Paco.size() == 0 );
assertTrue( Lola.size() == 1 );
}}
{{ // test::no_swap()
Bin_Tree<E> T = E(); // E() //
Bin_Tree<E> Right; // \ //
T.makeRightChild( E() ); // E() //
assertTrue( T.size() == 2 );
assertTrue( T.right().isRightChild() ); // Ahí está el hijo derecho
Right = T.right(); // no compila >==> T.left().swap( T.right() );
T.left().swap( Right );
assertTrue( T.right().isRightChild() ); // El hijo derecho no ha cambiado
assertTrue( T.size() == 2 );
T.makeLeftChild( T.right() ); // E() //
assertTrue( T.size() == 3 ); // / \ //
assertTrue( T.left().same( T.right()) ); // \ / //
assertTrue( T.right().isRightChild() ); // E() //
assertTrue( T.left().isLeftChild() ); // hijo compartido
T.makeLeftChild( T.right() ); // ahora sí cambió el árbol
T.makeRightChild( Bin_Tree<E>() ); // borra al hijo derecho
assertTrue( T.size() == 2 );
assertTrue( ! T.left().same( T.right()) );
assertTrue( ! T.right().isRightChild() ); // si hay hijo derecho
assertTrue( T.left().isLeftChild() ); // Ahí está el antiguo hijo derecho
}}
Definition at line 396 of file Bin_Tree.h.
| void Bin_Tree< E >::changeRoot | ( | const value_type & | d | ) | [inline] |
Sustituye por "d" el valor almacenado en la raíz del árbol.
Definition at line 478 of file Bin_Tree.h.
| void Bin_Tree< E >::changeLeftChild | ( | const value_type & | d | ) | [inline] |
Sustituye por "d" el valor almacenado en el hijo izquierdo del árbol.
"d"."d"."*this" está vacío.
{{ // test::changeChild()
Bin_Tree<char> T, Tcopy;
T = 'A'; // agrega la raiz 'A' A
T.changeLeftChild( '0' ); // ./ \.
T.changeRightChild( '1' ); // 0 1
copyDeep( Tcopy , T );
assertTrue( TestCase::toString(T) == "(A (0) (1))" );
mirror( T );
assertTrue( TestCase::toString(T) == "(A (1) (0))" );
mirror( T ); {
std::basic_ostringstream<char> ost;
ost << T;
assertTrue( ost.str() == "(A (0) (1))" );
}
assertTrue( comp(T, Tcopy) );
}}
Definition at line 497 of file Bin_Tree.h.
| void Bin_Tree< E >::changeRightChild | ( | const value_type & | d | ) | [inline] |
Sustituye por "d" el valor almacenado en el hijo derecho del árbol.
"d"."d"."*this" está vacío.
{{ // test::changeChild()
Bin_Tree<char> T, Tcopy;
T = 'A'; // agrega la raiz 'A' A
T.changeLeftChild( '0' ); // ./ \.
T.changeRightChild( '1' ); // 0 1
copyDeep( Tcopy , T );
assertTrue( TestCase::toString(T) == "(A (0) (1))" );
mirror( T );
assertTrue( TestCase::toString(T) == "(A (1) (0))" );
mirror( T ); {
std::basic_ostringstream<char> ost;
ost << T;
assertTrue( ost.str() == "(A (0) (1))" );
}
assertTrue( comp(T, Tcopy) );
}}
Definition at line 522 of file Bin_Tree.h.
Pone al árbol "T" como sub-árbol izquierdo de "*this".
"*this" si "T" está vacío."T" puede ser hijo de muchos árboles, pero el que es reportado como su padre es el último para el que se usó makeLeftChild(T) o makeRightChild(T).
! isEmpty() {{ // test::no_swap()
Bin_Tree<E> T = E(); // E() //
Bin_Tree<E> Right; // \ //
T.makeRightChild( E() ); // E() //
assertTrue( T.size() == 2 );
assertTrue( T.right().isRightChild() ); // Ahí está el hijo derecho
Right = T.right(); // no compila >==> T.left().swap( T.right() );
T.left().swap( Right );
assertTrue( T.right().isRightChild() ); // El hijo derecho no ha cambiado
assertTrue( T.size() == 2 );
T.makeLeftChild( T.right() ); // E() //
assertTrue( T.size() == 3 ); // / \ //
assertTrue( T.left().same( T.right()) ); // \ / //
assertTrue( T.right().isRightChild() ); // E() //
assertTrue( T.left().isLeftChild() ); // hijo compartido
T.makeLeftChild( T.right() ); // ahora sí cambió el árbol
T.makeRightChild( Bin_Tree<E>() ); // borra al hijo derecho
assertTrue( T.size() == 2 );
assertTrue( ! T.left().same( T.right()) );
assertTrue( ! T.right().isRightChild() ); // si hay hijo derecho
assertTrue( T.left().isLeftChild() ); // Ahí está el antiguo hijo derecho
}}
Definition at line 552 of file Bin_Tree.h.
Pone al árbol "T" como sub-árbol derecho de "*this".
"*this" si "T" está vacío."T" puede ser hijo de muchos árboles, pero el que es reportado como su padre es el último para el que se usó makeLeftChild(T) o makeRightChild(T).
! isEmpty() {{ // test::no_swap()
Bin_Tree<E> T = E(); // E() //
Bin_Tree<E> Right; // \ //
T.makeRightChild( E() ); // E() //
assertTrue( T.size() == 2 );
assertTrue( T.right().isRightChild() ); // Ahí está el hijo derecho
Right = T.right(); // no compila >==> T.left().swap( T.right() );
T.left().swap( Right );
assertTrue( T.right().isRightChild() ); // El hijo derecho no ha cambiado
assertTrue( T.size() == 2 );
T.makeLeftChild( T.right() ); // E() //
assertTrue( T.size() == 3 ); // / \ //
assertTrue( T.left().same( T.right()) ); // \ / //
assertTrue( T.right().isRightChild() ); // E() //
assertTrue( T.left().isLeftChild() ); // hijo compartido
T.makeLeftChild( T.right() ); // ahora sí cambió el árbol
T.makeRightChild( Bin_Tree<E>() ); // borra al hijo derecho
assertTrue( T.size() == 2 );
assertTrue( ! T.left().same( T.right()) );
assertTrue( ! T.right().isRightChild() ); // si hay hijo derecho
assertTrue( T.left().isLeftChild() ); // Ahí está el antiguo hijo derecho
}}
Definition at line 577 of file Bin_Tree.h.
| void Bin_Tree< E >::releaseLeftChild | ( | ) | [inline] |
Elimina el hijo izquierdo del árbol.
makeLeftChild( Bin_Tree<E>() );
{{ // test::releaseChild()
Bin_Tree<E> Paco = E(); // Paco Lola //
Bin_Tree<E> Lola = E(); // //
Bin_Tree<E> Bebe; // E() E() //
Lola.makeLeftChild( E() ); // \\ / //
Bebe = Lola.left(); // Bebe //
Bebe.makeLeftChild( E() ); // // \\ //
Bebe.makeRightChild( E() ); // E() E() //
Paco.makeRightChild( Bebe );
Paco.releaseLeftChild();
assertTrue( 4 == Paco.size() ); // Paco no tiene hijo izquierdo
Paco.releaseRightChild();
assertTrue( 1 == Paco.size() ); // Ya Paco no tiene hijo derecho
assertTrue( Paco.right() == Bin_Tree<E>() ); // El hijo derecho es un árbol vacío
assertTrue( Bebe != Bin_Tree<E>() ); // Bebe todavía existe
assertTrue( Bebe.father() == Paco ); // Paco sigue registrado como padre de Bebe
assertTrue( 4 == Lola.size() ); // Lola todavía tiene a su hijo izquierdo
assertTrue( Bebe.same( Lola.left() ) ); // Bebe si es hijo izquierdo de Lola
assertTrue( Lola.left().same( Bebe ) ); // Lola si tiene hijo izquierdo
assertTrue( Bebe.father() != Bin_Tree<E>() ); // Bebe no está registrado como hijo de Lola
Lola.releaseLeftChild(); // Ahora ya Bebe no es hijo de Lola
assertTrue( ! Bebe.same( Lola.left() ) );
assertTrue( 1 == Lola.size() ); // Ya Lola no tiene hijos
}}
Definition at line 611 of file Bin_Tree.h.
| void Bin_Tree< E >::releaseRightChild | ( | ) | [inline] |
Elimina el hijo derecho del árbol.
makeLeftChild( Bin_Tree<E>() );
{{ // test::releaseChild()
Bin_Tree<E> Paco = E(); // Paco Lola //
Bin_Tree<E> Lola = E(); // //
Bin_Tree<E> Bebe; // E() E() //
Lola.makeLeftChild( E() ); // \\ / //
Bebe = Lola.left(); // Bebe //
Bebe.makeLeftChild( E() ); // // \\ //
Bebe.makeRightChild( E() ); // E() E() //
Paco.makeRightChild( Bebe );
Paco.releaseLeftChild();
assertTrue( 4 == Paco.size() ); // Paco no tiene hijo izquierdo
Paco.releaseRightChild();
assertTrue( 1 == Paco.size() ); // Ya Paco no tiene hijo derecho
assertTrue( Paco.right() == Bin_Tree<E>() ); // El hijo derecho es un árbol vacío
assertTrue( Bebe != Bin_Tree<E>() ); // Bebe todavía existe
assertTrue( Bebe.father() == Paco ); // Paco sigue registrado como padre de Bebe
assertTrue( 4 == Lola.size() ); // Lola todavía tiene a su hijo izquierdo
assertTrue( Bebe.same( Lola.left() ) ); // Bebe si es hijo izquierdo de Lola
assertTrue( Lola.left().same( Bebe ) ); // Lola si tiene hijo izquierdo
assertTrue( Bebe.father() != Bin_Tree<E>() ); // Bebe no está registrado como hijo de Lola
Lola.releaseLeftChild(); // Ahora ya Bebe no es hijo de Lola
assertTrue( ! Bebe.same( Lola.left() ) );
assertTrue( 1 == Lola.size() ); // Ya Lola no tiene hijos
}}
Definition at line 624 of file Bin_Tree.h.
| void Bin_Tree< E >::makeOrphan | ( | ) | [inline] |
Desconecta al hijo del padre.
"*this" continúa registrado como hijo de su padre.
{{ // test::makeOrphan()
Bin_Tree<E> Paco = E(); // Paco Lola //
Bin_Tree<E> Lola = E(); // //
Bin_Tree<E> Bebe; // E() E() //
Lola.makeLeftChild( E() ); // \\ / //
Bebe = Lola.left(); // Bebe //
Bebe.makeLeftChild( E() ); // // \\ //
Bebe.makeRightChild( E() ); // E() E() //
Paco.makeRightChild( Bebe );
assertTrue( Bebe.same( Lola.left() ) ); // Bebe si es hijo izquierdo de Lola
assertTrue( Bebe.same( Paco.right() ) ); // Bebe si es hijo derecho de Paco
assertTrue( Bebe.father() == Paco ); // Bebe está registrado como hijo de Paco
assertTrue( Bebe.father() != Lola ); // Bebe no está registrado como hijo de Lola
Bebe.makeOrphan();
assertTrue( Bebe.father() != Paco ); // Ya Paco no está registrado como el padre de Bebe
assertTrue( Bebe.father() == Bin_Tree<E>() ); // Bebe no tiene registrado a nadie como su padre
assertTrue( Bebe.same( Lola.left() ) ); // Bebe sigue registrado como hijo izquierdo de Lola
assertTrue( Bebe.same( Paco.right() ) ); // Bebe sigue registrado como hijo derecho de Paco
assertTrue( Bebe.father() != Paco ); // Bebe ya no está registrado como hijo de Paco
assertTrue( Bebe.father() != Lola ); // Bebe ya no está registrado como hijo de Lola
}}
Definition at line 638 of file Bin_Tree.h.
| value_type& Bin_Tree< E >::data | ( | ) | const [inline] |
Valor almacenado en la raíz del sub-árbol.
!isEmpty() Definition at line 140 of file Bin_Tree.h.
| value_type& Bin_Tree< E >::operator* | ( | ) | const [inline] |
Valor almacenado en la raíz del sub-árbol.
!isEmpty() Definition at line 143 of file Bin_Tree.h.
| value_type* Bin_Tree< E >::operator-> | ( | ) | const [inline] |
Puntero al valor almacenado en la raíz del sub-árbol.
!isEmpty() Definition at line 146 of file Bin_Tree.h.
Acceso al padre.
Definition at line 170 of file Bin_Tree.h.
Acceso al hijo izquierdo.
makeLeftChild().
{{ // test::left_right()
Bin_Tree<E> T = E(); // no hay hijo izquierdo alguno
{ T.left() = E(); // sí hace el cambio
// pero el destructor elimina la referencia
} // sin modificar el hijo izquierdo que no existe
assertTrue( T.size() == 1 );
assertTrue( T.left().isEmpty() ); // "T.left()" es una nueva referencia al hijo de "T"
T.makeRightChild( E() ); // esta es la forma de crear un nuevo sub-árbol derecho
T.right().erase(); // no elimina al hijo derecho: borra la nueva referencia "right()"
assertTrue( T.size() == 2 );
assertTrue( ! T.right().isEmpty() ); // el hijo derecho está ahí todavía
{ // Para eliminar a un hijo hay que poner el árbol nulo en su lugar
T.right() =