Está en la página 1de 116

Tema 3

Arboles
Gabriel Navarro
Estructuras de Datos
Grado en Ingeniera Informatica
Gabriel Navarro Tema 3

Arboles

Indice
Concepto de arbol
Recorridos en arboles

Arboles binarios

Arboles binarios: Implementacion con celdas enlazadas


Iteradores

Arboles de expresiones

Arboles binarios de busqueda (ABB)

Arboles binarios de busqueda balanceados (AVL)

Arboles parcialmente ordenados (APO)

Arboles n-arios
Gabriel Navarro Tema 3

Arboles
Concepto de arbol
Un arbol es una estructura de datos no lineal, en la que cada
elemento (nodo) tiene un unico elemento anterior denominado
padre (menos la raz, que no tiene ninguno), y puede tener mas de
un elemento siguiente (hijos del nodo).
Los arboles son estructuras jerarquicas que permiten organizar la
informacion de acuerdo a unos criterios de jerarqua.
Denicion recursiva
Un nodo es un arbol.
Un arbol vaco (0 nodos) es un arbol.
Si tomamos n arboles y cada una de sus races has hacemos
hijo de un nodo, el resultado es un arbol.
Gabriel Navarro Tema 3

Arboles
Concepto de arbol: Ejemplo
Tierra
Antartida Europa
Espana Alemania
America

Africa
Somalia Argelia
Gabriel Navarro Tema 3

Arboles

Arboles: Terminologa
Relacion entre nodos: El que esta por encima se llama padre y, el de
abajo, hijo.
El nodo raz es el que no tiene padre.
Los nodos hoja son aquellos que no tienen hijos.
Nodos hermanos son aquellos que comparten padre.
Un nodo interior es aquel que tiene hijos. En caso contrario, se dice
que el nodo es exterior.
La profundidad de un nodo es el numero de relaciones padre-hijo
que hay que seguir entre el nodo y la raz del arbol.
Un nivel es un conjunto de nodos que se encuentran a la misma
profundidad.
Gabriel Navarro Tema 3

Arboles

Arboles: Terminologa
La altura de un nodo es el numero ed relaciones padre-hijo que hay
que seguir entre el nodo y su descendiente mas lejano. Se llama
estructura del arbol a la altura de la raz.
Un subarbol es un nodo de un arbol junto con todos sus
descendientes.
Un arbol parcial es un arbol que contiene unicamente algunos nodos
del arbol original.
CUIDADO!!
Recordar bien la diferencia entre altura y profundidad.
Gabriel Navarro Tema 3

Arboles

Arboles: Recorridos
Se llama recorrido de un arbol al orden establecido en el que se
debe visitar los nodos de un arbol. Existen varios tipos de
recorridos, donde los mas comunes son:
Preorden: Raz > Hijo Izquierda > Hijos Derecha.
Inorden: Hijo Izquierda > Raz > Hijos Derecha.
Postorden: Hijo Izquierda > Hijos Derecha > Raz.
Por niveles: Nodos de un nivel, de izquierda a derecha. Pasar
al siguiente nivel.
Gabriel Navarro Tema 3

Arboles

Arboles: Recorrido en preorden


A
B
E
F G
H Q
J K
I
C D
L M N
O P
Recorrido= A, B, E, F, G, H, Q, J, K, I, C, D, L, M, N, O, P
Gabriel Navarro Tema 3

Arboles

Arboles: Recorrido en inorden


A
B
E
F G
H Q
J K
I
C D
L M N
O P
Recorrido= F, E, H, G, J, Q, K, I, B, A, C, L, D, M, O, N, P
Gabriel Navarro Tema 3

Arboles

Arboles: Recorrido en postorden


A
B
E
F G
H Q
J K
I
C D
L M N
O P
Recorrido= F, H, J, K, Q, I, G, E, B, C, L, M, O, P, N, D, A
Gabriel Navarro Tema 3

Arboles

Arboles: Recorrido por niveles


A
B
E
F G
H Q
J K
I
C D
L M N
O P
Recorrido= A, B, C, D, E, L, M, N, F, G, O, P, H, Q, I, J, K
Gabriel Navarro Tema 3

Arboles
ARBOLES BINARIOS
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Representacion con celdas enlazadas


Cada nodo del arbol sera representado mediante una celda. Llamaremos
celda a una estructura o clase que contenga el valor o etiqueta de un
elemento de la lista y una referencia a su padre, a su hijo izquierdo y a su
hijo derecho. La referencia la implementaremos como un puntero.
struct celda {
int et;
celda *padre; // Puntero al nodo padre
celda *hi; // Puntero al hijo izquierdo
celda *hd; // Puntero al hijo derecho
};
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Representacion con celdas enlazadas


Con esta representacion, Nodo de un arbol es la referencia a la zona de
memoria de la celda que lo contiene. Celda se declara como una subclase
de Lista:
template <class Elemento>
class ArbolBinario {
...
public:
class Celda {
private:
Elemento et;
Celda * padre, hi, hd;
public:
...
friend class ArbolBinario; // Para permitir al arbol acceder a los atributos
};
typedef Celda * Nodo;
...
};
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Representacion con celdas enlazadas


Representacion del arbol
Celda *raiz; /**< Nodo raz del arbol */
Funcion de Abstraccion
Dado el tipo representado rep={raiz}, el objeto al que representa
es un arbol L tal que raiz es la raz del arbol, raiz->hi contiene su
hijo izquierdo y raiz->hd contiene su hijo a la derecha.
Recursivamente raiz->hi y raiz->hd seran a su vez subarboles del
arbol original.
Invariante de la Representacion
rep.raiz es null. En caso contrario, rep.raiz->padre es null. Para
todo nodo del arbol N, N->hi apunta a su hijo izquierdo, o vale
null en caso de no tener. N->hd apunta a su hijo derecho, o vale
null en caso de no tener.
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Implementacion con celdas enlazadas


Ver Especicacion Completa
Ver Implementacion Completa
Lo mas relevante:
Como gestionar arboles vacos y la reserva de memoria.
Insercion de hijos.
Poda.
Conocer el n umero de nodos del arbol.
Conocer la altura y la profundidad de un nodo.
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Implementacion. Celdas


El constructor de una celda debera asignar los campos padre, hijo
izquierda e hijo derecha a NULL, ya que una celda no tiene
inicialmente padre ni hijos.
Celda() { padre= hi= hd= 0; }
Partiremos de esta premisa para implementar las funciones de insercion
de nodos en el arbol.
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Implementacion. Gestion de arboles


vacos
Diremos que el arbol estara vaco si raiz==0. Por tanto, cada
constructor debera inicializar raiz= 0; antes de realizar cualquier
operacion.
template <class T>
ArbolBin<T>::ArbolBin() { raiz= 0; }
template <class T>
ArbolBin<T>::ArbolBin(const ArbolBin<T> &a) {
raiz= 0; *this= a;
}
template <class T>
bool ArbolBin<T>::estaVacio() {
return raiz == 0;
}
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Implementacion. Gestion de arboles


vacos
Existe un metodo en ArbolBin que elimina el arbol y lo hace vaco:
void ArbolBin<T>::vaciar() {
if (raiz != 0) { podar(raiz); raiz= 0; }
}
Este metodo debera realizar una poda del nodo raz, eliminando
todos sus hijos y el nodo en s. Posteriormente, asignara raiz= 0
para asegurar que se cumple la premisa de arbol vaco.
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Implementacion. Gestion de arboles


vacos
Dado que un arbol vaco no tiene memoria reservada para la raz,
la insercion de la misma diere de la insercion de otros nodos,
como los hijos.
El metodo void setRaiz(T valor ); se encarga de comprobar si la
raz esta reservada o no. Si lo esta, vaciara el arbol. En caso
contrario, reservara memoria para el nodo y le asignara su etiqueta.
void setRaiz(T valor) {
if (raiz != 0) vaciar();
// Recordar que new Celda() hace NULL el padre y los hijos
raiz= new (nothrow) Celda (); raiz->valor= valor;
}
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Insercion de hijos


La insercion de hijos implica varias tareas:
1 Comprobar que el nodo padre no es nulo.
2 Si existe el hijo a insertar, podarlo.
3 Crear un nuevo nodo, hijo del padre.
4 Asignar punteros del nuevo hijo.
void insertarHijoIzquierda(typename ArbolBin<T>::Nodo p, T
valor) {
if (p==0) return ;
if (p->hi != 0) podar(p->hi);
p->hi= new (nothrow) Celda ();
p->hi->valor= valor;
p->hi->padre= p; // Reasignamos el padre del hijo izq
}
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Poda


La poda puede realizarse mediante un procedimiento recursivo
como el siguiente:
1 Si el nodo a podar es nulo, hemos terminado. En otro caso,
seguir.
2 Descolgar el nodo del padre.
3 Podar el hijo izquierda y el Hijo derecha del nodo.
4 Eliminar el nodo y hacerlo nulo para evitar fallos.
5 Asignar punteros del nuevo hijo.
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Poda


void ArbolBin<T>::podar(ArbolBin<T>::Nodo &n) {
typename ArbolBin<T>::Nodo aux= n;
if (aux == 0) return ;
// Descolgamos nodo del padre
if (aux->padre != 0) {
if (aux->padre->hi == aux) aux->padre->hi= 0;
else aux->padre->hd= 0;
}
// Podamos hijos
podar(aux->hi);
podar(aux->hd);
// Eliminamos nodo
delete aux; n= 0;
}
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Conocer numero de nodos


Para conocer el n umero de nodos del arbol hay que implementar
alguno de los recorridos sobre arboles. Cada vez que se pase por
un nodo nuevo, se actualizara un contador de nodos. Al nalizar,
el valor del contador sera el n umero de nodos del arbol.
El recorrido puede ser cualquiera, y se puede implementar tanto
recursiva como iterativamente. Como ejemplo, lo hemos
implementado iterativamente utilizando una pila para eliminar la
recursividad.
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Conocer numero de nodos


int ArbolBin<T>::numNodos() const {
int suma= 0;
Pila<typename ArbolBin<T>::Nodo> p;
typename ArbolBin<T>::Nodo aux;
if (raiz == 0) return ;
// Recorremos en preorden el arbol.
// Por cada nodo no nulo, contabilizamos suma++
p.insertar(raiz);
while ( !p.estaVacia() ) {
aux= p.verElemento();
p.quitar();
suma++;
if (aux->hd != 0) p.insertar(aux->hd);
if (aux->hi != 0) p.insertar(aux->hi);
}
return suma;
}
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Conocer altura y profundidad


Tambien se implementan facilmente mediante procedimientos
recursivos. Suponiendo que un nodo inexistente tiene altura (H) y
profundidad (P) -1, para cualquier nodo N estas se calculan como:
H(N) =

1 ; N == 0
1 +max{H(N > hi), H(n > hd)} ;

P(N) =

1 ; N == 0
1 +P(N > padre) ;

Gabriel Navarro Tema 3



Arboles

Arboles binarios: Conocer altura y profundidad


int ArbolBin<T>::getAltura(typename ArbolBin<T>::Nodo n)
const {
int ahi, ahd, max;
if (n == 0) return -1;
ahi= getAltura(n->hi);
ahd= getAltura(n->hd);
max= (ahi<ahd)? ahd:ahi;
return max+1;
}
int ArbolBin<T>::getProfundidad(typename ArbolBin<T>::Nodo
n) const {
if (n == 0) return -1;
return 1+getProfundidad(n->padre);
}
Gabriel Navarro Tema 3

Arboles

Arboles binarios: Ejemplo de uso


main() {
ArbolBin<char> arbol, arbol2;
typename ArbolBin<char>::Nodo aux;
// Rellenamos arbol
arbol.setRaiz(A);
aux= arbol.getRaiz();
arbol.insertarHijoIzq(aux, B);
arbol.insertarHijoDcha(aux, C);
aux= arbol.getHijoIzq(arbol.getRaiz());
arbol.insertarHijoIzq(aux, D);
arbol.insertarHijoDcha(aux, E);
aux= arbol.getHijoDcha(arbol.getRaiz());
arbol.insertarHijoIzq(aux, F);
arbol.insertarHijoDcha(aux, G);
aux= arbol.getHijoDcha(aux);
arbol.insertarHijoDcha(aux, H);
....
}
Gabriel Navarro Tema 3

Arboles
ITERADORES
Gabriel Navarro Tema 3

Arboles
Iteradores
Ejemplo:
for (int i= 0; i<N; i++) {
cout<<vector[i]<<endl;
}
Normalmente, a la variable i del ejemplo se le conoce como
iterador.
Un Iterador es un objeto abstracto que nos permite recorrer los
elementos de otro tipo de dato, abstrayendo el procedimiento para
conocer cual elemento es anterior o posterior a otro elemento.
Necesidad de implementar iteradores
En un vector o una lista es obvio cual elemento es siguiente o
anterior a otro elemento. Pero, por ejemplo en un arbol, que
criterio se tomara?
Gabriel Navarro Tema 3

Arboles
Iteradores en arboles
Si deseamos visitar los nodos de un arbol, debemos implementar
uno de los recorridos.
Mediante el uso de iteradores, podemos abstraer el concepto del
recorrido de modo que el programador quede liberado del
conocimiento del mismo.
Recorrido ideal en Preorden de un arbol con Iteradores
...
ArbolBin<int> arbol;
...
for (IteradorPreorden i(arbol); i! =i.nal(); i++)
cout<<arbol.getEtiqueta(i.getNodoActual());
...
Al abstrer el recorrido en preorden en el ejemplo anterior, el codigo
queda mucho mas legible, y puede ser facilmente modicado en el
futuro con solo modicar el iterador.
Gabriel Navarro Tema 3

Arboles
Iteradores en arboles
Al dise nar un iterador en un arbol, lo primero que hay que
establecer es un criterio para saber cual es el elemento siguiente
para cada nodo. Este criterio puede imponerse si utilizamos los
recorridos en arboles:
Preorden: El siguiente del padre es el hijo a la izquierda. Su
siguiente, el hermano a la derecha.
Inorden: El siguiente del hijo a la izquierda es el padre. Su
siguiente, el hijo a la derecha.
Postorden: El siguiente del hijo a la izquierda es el hermano a la
derecha. Su siguiente, el padre.
Niveles: El siguiente de un nodo es su hermano a la derecha. Su
siguiente, el hijo a la izquierda.
Gabriel Navarro Tema 3

Arboles
Iteradores: Metodos comunes
Todo iterador debe implementar mecanismos para:
Inicializar el iterador al primer elemento a visitar.
Conocer cuando se ha terminado de visitar todos los
elementos.
Pasar al siguiente elemento a visitar.
Obtener el valor del elemento actual que se esta visitando.
Gabriel Navarro Tema 3

Arboles
Iteradores: Implementacion en arboles
La interfaz de todo iterador, para arboles binarios, debe
implementarse como subclase y ser similar a la siguiente:
class Iterador {
private:
typename ArbolBin<Elemento>::Nodo actual;
public:
Iterador(const ArbolBin<Elemento> &a);
bool nal();
typename ArbolBin<Elemento>::Nodo getNodo();
bool operator!=(typename ArbolBin<Elemento>::Nodo n);
}
Gabriel Navarro Tema 3

Arboles
Iteradores: Implementacion en arboles. Ejemplo.
template <class T>
class ArbolBin {
...
public:
class IteradorPreorden {
private:
typename ArbolBin<T>::Nodo actual;
public:
Iteradorpreorden(const ArbolBin<T> &a);
bool nal();
typename ArbolBin<T>::Nodo getNodo();
bool operator!=(typename ArbolBin<T>::Nodo n);
};
...
};
Gabriel Navarro Tema 3

Arboles
Iteradores: Implementacion en arboles. Ejemplo.
template <class T>
ArbolBin<T>::IteradorPreorden::IteradorPreorden(const
ArbolBin<T> &a) {
actual= a.getRaiz();
}
template <class T>
ArbolBin<T>::IteradorPreorden::nal() {
return 0;
}
template <class T>
typename ArbolBin<T>::Nodo
ArbolBin<T>::IteradorPreorden::getNodo() {
return actual;
}
Gabriel Navarro Tema 3

Arboles
Iteradores: Implementacion en arboles. Ejemplo.
template <class T>
ArbolBin<T>::IteradorPreorden::operator++(int j) {
if ( actual->hi != 0 ) actual= actual->hi;
else if ( actual->hd != 0 ) actual= actual->hd;
else {
if ( actual->padre != 0 ) {
while ( (actual->padre != 0) && (actual->padre->hd ==
actual) )
actual= actual->padre;
if ( actual->padre != 0 ) actual= actual->padre->hd;
else actual= actual->padre;
} else actual= actual->padre;
}
return *this;
}
Gabriel Navarro Tema 3

Arboles
Iteradores: Ejemplo de uso
template <class T>
void MostrarPreorden(ArbolBin<T> a) {
for (ArbolBin<T>::IteradorPreorden it(a); it!=it.nal(); it++) {
cout<<a.getEtiqueta(it.getNodo()) << ;
}
cout<<endl;
}
main(){
ArbolBin<int>arbol(9);
...
MostrarPreorden<int>(arbol);
...
}
Gabriel Navarro Tema 3

Arboles
Iteradores: Ejemplo de uso
template <class T>
void MostrarInorden(ArbolBin<T> a) {
for (ArbolBin<T>::IteradorInorden it(a); it!=it.nal(); it++) {
cout<<a.getEtiqueta(it.getNodo()) << ;
}
cout<<endl;
}
main(){
ArbolBin<int>arbol(9);
...
MostrarInorden<int>(arbol);
...
}
Gabriel Navarro Tema 3

Arboles
Iteradores: Implementacion en arboles binarios
Ver Especicacion Completa
Ver Implementacion Completa
Gabriel Navarro Tema 3

Arboles
ARBOLES DE EXPRESIONES
Gabriel Navarro Tema 3

Arboles
Denicion de arbol de expresion
Denicion
Un arbol de expresiones es un tipo especial de arbol que permite
representar expresiones matematicas. En sus nodos internos, el
arbol contiene las operaciones a realizar. En los nodos hoja, los
operandos.
Dado que la mayora de operadores matematicos son unarios o
binarios, los arboles de expresion mas comunes son los arboles de
expresion binarios.
Si la operacion de un nodo de un arbol de expresion binario tiene
dos operandos, ese nodo debera tener dos hijos. Si es unario,
tendra un unico hijo a la derecha.
Gabriel Navarro Tema 3

Arboles
Ejemplo de arbol de expresion
+
-
8
*
3 -
X 7
Recorrido en Inorden: -8+3*X-7
Recorrido en Preorden: +-8*3-X7
Recorrido en Postorden: 8-3X7-*+
Si los nodos de un arbol de expresion pueden tener uno o dos hijos,
ninguno de los recorridos del arbol puede darnos el arbol original
asociado. Para ello, podramos imponer que todos los nodos
tengan dos hijos.
Gabriel Navarro Tema 3

Arboles
Ejemplo de arbol de expresion
+
-
0 8
*
3 -
X 7
Recorrido en Inorden: 0-8+3*X-7
Recorrido en Preorden: +-08*3-X7
Recorrido en Postorden: 08-3X7-*+
La expresion en inorden es mas legible por un humano. No
obstante, puede no corresponder al arbol que la origino a no ser
que este parentizada: 0-8+3*(X-7).
Tanto el recorrido en preorden como el recorrido en postorden
permiten recuperar el arbol original de la expresion.
Gabriel Navarro Tema 3

Arboles
ARBOLES BINARIOS DE
B

USQUEDA
Gabriel Navarro Tema 3

Arboles

Arboles Binarios de Busqueda


Un arbol binario de b usqueda (ABB) es un arbol binario que
cumple las siguientes propiedades:
Es un arbol binario.
La etiqueta de cada nodo del arbol es menor que cualquiera
de los descendientes por su izquierda.
La etiqueta de cada nodo del arbol es mayor que cualquiera
de los descendientes por su derecha.
Ejemplo:
20
9
8 16
36
25 40
38 50
El recorrido en inorden de un arbol binario de b usqueda
proporciona el conjunto de nodos del arbol ordenados.
Gabriel Navarro Tema 3

Arboles

Arboles Binarios de Busqueda


Denicion
Se dice que un ABB esta equilibrado cuando, para cualquier nodo
del arbol, la diferencia entre la altura de sus hijos no es superior a
1 (respectivamente, inferior a -1)
Ejemplo:
20
9
8 16
36
25 40
38 50
20
9
8 16
36
25 40
38 50
52
Esta equilibrado No esta equilibrado en 36.
Gabriel Navarro Tema 3

Arboles

Arboles Binarios de Busqueda


Los arboles binarios de b usqueda son la base para arboles mas
complejos como los ndices.
Se utilizan para reducir la b usqueda de elementos. Si el arbol esta
equilibrado esta tiene un coste de O(log(n)).
La insercion en un ABB la realiza el arbol autom aticamente en el
nodo hoja que le corresponda, seg un el valor de la etiqueta del
nodo.
Para preservar las propiedades del arbol, el borrado de nodos en un
ABB se realiza sustituyendo el elemento a eliminar por:
O bien el descendiente a la izquierda con valor de etiqueta
mayor.
O bien el descendiente a la derecha con valor de etiqueta
menor.
Gabriel Navarro Tema 3

Arboles
ABB: Representaciones
Un ABB puede representarse a partir de un arbol binario:
Por herencia de arbol binario.
Incluyendo un arbol binario como dato miembro del ABB.
Existen tantas implementaciones posibles de ABBs como dise nos
del programador que lo implemente, aunque las dos anteriores
estan bastante extendidas.
Ver Implementacion con herencia
Ver Implementacion con datos miembro
Gabriel Navarro Tema 3

Arboles
ABB: Representacion con datos miembro
Representacion del arbol
ArbolBin<T> L; /**< Arbol binario que representa al ABB */
Funcion de Abstraccion
Dado el tipo representado rep={raiz}, el objeto al que representa
es un arbol L tal que raiz es la raz del arbol, raiz->hi contiene su
hijo izquierdo y raiz->hd contiene su hijo a la derecha.
Recursivamente raiz->hi y raiz->hd seran a su vez subarboles del
arbol original.
Invariante de la Representacion
rep.raiz es null. En caso contrario, rep.raiz->padre es null. Para
todo nodo del arbol N, N->hi apunta a su hijo izquierdo, o vale
null en caso de no tener. N->hd apunta a su hijo derecho, o vale
null en caso de no tener. Para cada nodo N, si sus hijos existen
entonces N->valor>N->hi->valor y N->valor<N->hd->valor.
Gabriel Navarro Tema 3

Arboles
ABB: Interfaz
template <class T>
class ABB {
public:
ABB(); ABB(const ABB<T> &a); ABB(T valor); ABB();
typename ArbolBin<T>::Nodo getRaiz();
T getEtiqueta(typename ArbolBin<T>::Nodo n);
typename ArbolBin<T>::Nodo getPadre(typename
ArbolBin<T>::Nodo n);
typename ArbolBin<T>::Nodo getHijoIzq(typename
ArbolBin<T>::Nodo n);
typename ArbolBin<T>::Nodo getHijoDcha(typename
ArbolBin<T>::Nodo n);
void insertar(T valor);
podar, vaciar, estaVacio, etc... (procedentes de ArbolBin)
};
Gabriel Navarro Tema 3

Arboles
ABB: Interfaz
Ejercicio
Implementar la funcion de b usqueda
Gabriel Navarro Tema 3

Arboles
ABB: Interfaz
Ejercicio
Implementar la funcion de b usqueda
typename ArbolBin<T>::Nodo ABB<T>::BUSCAR (
typename ArbolBin<T>::Nodo arbol,T valor){
typename ArbolBin<T>::Nodo aux=0;
if ( arbol!=0 ){
if ( valor < arbol->et)// arbol izquierdo
aux = BUSCAR(arbol->hi,valor);
else if ( valor > arbol->et ) // arbol derecho
aux = BUSCAR(arbol->hd,valor);
else aux=T;
}
return aux;
}
Gabriel Navarro Tema 3

Arboles
ABB: Insercion de elementos en el arbol
bool Insertar(typename ArbolBinT::Nodo raiz, T valor);
El procedimiento de insercion es el siguiente:
1 Si el arbol esta vaco crear la raz y asignarle valor. Devuelve
true.
2 En otro caso:
1 Si la etiqueta de aux<valor, aplicar Insertar(aux -> hd, valor).
2 Si la etiqueta de aux>valor, aplicar Insertar(aux -> hi, valor).
3 Si la etiqueta de aux=valor, el valor ya estaba y devuelve false.
Ver Implementacion Completa
Gabriel Navarro Tema 3

Arboles
ABB: Insercion de elementos en el arbol
bool ABB<T>::Insertar (typename ArbolBin<T>::Nodo raiz, T valor)
{
bool res=1 // exito si no esta en el arbol
if (raiz==0){
raiz=new typename ArbolBin<T>::Nodo ();
raiz -> et = valor;
}
else if (valor < raiz -> et) // arbol izq.
res= Insertar (raiz -> hi, valor);
else if (valor > raiz -> et) // arbol der.
res= Insetar (raiz -> hd, valor);
else
res=false; // el valor ya est a
return res;
}
Gabriel Navarro Tema 3

Arboles
ABB: Borrado de elementos en el arbol
Borrar un valor
Para borrar un valor V en un nodo N:
Si N no tiene hijos, simplemente se elimina el nodo
Si N tiene un hijo, se elimina el nodo y el hijo pasa a ocupar
su lugar
Si N tiene dos hijos:
se busca el elemento anterior H (o el siguiente), es decir,
izquierda - derecha - derecha - derecha ... hasta un nodo hoja.
se cambia el valor de N por el de H
se elimina el nodo H.
Gabriel Navarro Tema 3

Arboles
ABB: Borrado de elementos en el arbol
bool ABB<T>::Borrar (typename ArbolBin<T>::Nodo raiz, T valor){
bool res=1 // exito si estaba en el arbol
if (raiz==0) res=false;
else if (valor < raiz -> et) // arbol izq.
res= Borrar (raiz -> hi, valor);
else if (valor > raiz -> et) // arbol der.
res= Borrar (raiz -> hd, valor);
else{ // localizado
EliminarRaiz(raiz);
res=true;
}
return res;
}
Gabriel Navarro Tema 3

Arboles
ABB: Borrado de elementos en el arbol
void ABB<T>::EliminarRaiz (typename ArbolBin<T>::Nodo raiz){
if (raiz -> hi==0 && raiz -> hd ==0 ){// sin hijos
delete raiz;
raiz = 0;
}
else if ( raiz -> hi == 0 ){ // solo hijo derecha
typename ArbolBin<T>::Nodo aux =raiz;
raiz = raiz -> hd;
delete aux;
}
else if ( raiz -> hd == 0 ){ // solo hijo izq.
typename ArbolBin<T>::Nodo aux =raiz;
raiz = raiz -> hd;
delete aux;
}
else {// tiene dos hijos
typename ArbolBin<T>::Nodo aux =raiz -> hd;
while (aux -> hi !=0 )
aux = aux -> hi;
raiz -> et = aux -> et;
Borrar (raiz -> hd, aux -> et);
}
}
Gabriel Navarro Tema 3

Arboles
ARBOLES AVL
Gabriel Navarro Tema 3

Arboles

Arboles AVL
Un

AVL es un arbol binario de b usqueda que siempre esta
equilibrado (condicion de Adelson, Velskii y Landis).
Ejemplo:
20
9
8 16
36
25 40
38 50
El arbol esta equilibrado siempre que la diferencia de alturas de sus
hijos no exceda el valor 1 (en valor absoluto).
Gabriel Navarro Tema 3

Arboles

Arboles AVL
Las representaciones, interfaz y funcion de abstraccion del AVL son
identicas a las de un ABB. Cambia levemente el invariante de la
representacion:
Invariante de la Representacion
rep.raiz es null. En caso contrario, rep.raiz->padre es null. Para
todo nodo del arbol N, N->hi apunta a su hijo izquierdo, o vale
null en caso de no tener. N->hd apunta a su hijo derecho, o vale
null en caso de no tener. Para cada nodo N, si sus hijos existen
entonces N->valor>N->hi->valor y N->valor<N->hd->valor.
Para todo nodo N, |altura(H->hi)-altura(N->hd)| <=1.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Insercion


La insercion en un AVL tambien es identica a la del ABB. Sin
embargo, tras realizar esta, hay que vericar que el arbol esta
equilibrado comenzando desde el padre del nodo insertado hasta la
raz:
1 aux= padre del nodo insertado.
2 Mientras (aux != NULL), hacer:
1 Calcular alturas de aux->hi y aux->hd
2 Si aux esta desequilibrado, entonces equilibrar.
3 En caso contrario, aux= aux->padre
Supondremos que la altura de un nodo inexistente en el arbol es -1
para la implementacion de los apuntes.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Equilibrado


El equilibrado de nodos en un arbol AVL se realiza mediante
rotaciones de nodos dentro del arbol. Podemos distinguir 4 casos:
Rotacion simple a la derecha.
Rotacion simple a la izquierda.
Rotacion doble izquierda-derecha.
Rotacion doble derecha-izquierda.
El tipo de rotacion de nodos a realizar dependera de la situacion
dada en el arbol.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Equilibrado


Rotacion simple a derecha
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Equilibrado


Rotacion simple a izquierda
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Equilibrado


Rotacion doble izquierda-derecha
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Equilibrado


Rotacion doble derecha-izquierda
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Algoritmo para conocer el tipo de


desequilibrio
Para equilibrar un nodo, antes hay que observar que tipo de
desequilibrio tiene:
1 Sea N un nodo desequilibrado.
2 Si H(N->hi) - H(N->hd) > 1, hay desequilibrio por la izquierda y:
1 Si H(N->hi->hi) > H(N->hi->hd), hay desequilibrio
izquierda-izquierda. Se aplica Rotacion simple a la derecha sobre
N->hi.
2 En otro caso, hay desequilibrio izquierda-derecha. Se aplica
Rotacion doble. Primero rotacion a la izquierda sobre
N->hi->hd, y rotacion a la derecha sobre el nuevo nodo N->hi.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Algoritmo para conocer el tipo de


desequilibrio
Para equilibrar un nodo, antes hay que observar que tipo de
desequilibrio tiene:
3 Si H(N->hi) - H(N->hd) < -1, hay desequilibrio por la derecha y:
1 Si H(N->hd->hd) > H(N->hd->hi), hay desequilibrio
derecha-derecha. Se aplica Rotacion simple a la izquierda sobre
N->hd.
2 En otro caso, hay desequilibrio derecha-izquierda. Se aplica
Rotacion doble. Primero rotacion a la derecha sobre N->hd->hi,
y rotacion a la izquierda sobre el nuevo nodo N->hd.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Ejercicios


Ejercicio
Implementar la funciones de rotacion en un AVL
Ejercicio
Implementar la funciones de insercion de un valor en un AVL
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Rotacion a la derecha. Ejemplo.


Insercion del valor 1 en el arbol:
20
15
10
40
20
15
10
1
40
Desequilibrio en 15:
H(15->hi)-H(15->hd)= 1-(-1)= 2.
(Desequilibrio izquierda)
H(15->hi->hi) > H(15->hi->hd),
1 > -1. (Desequilibrio
izquierda-izquierda)
Rotacion a la Derecha sobre 10.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Rotacion a la derecha. Ejemplo


Solucion:
20
10
1 15
40
Desequilibrio en 15:
H(15->hi)-H(15->hd)= 1-(-1)= 2.
(Desequilibrio izquierda)
H(15->hi->hi) > H(15->hi->hd),
1 > -1. (Desequilibrio
izquierda-izquierda)
Rotacion a la Derecha sobre 10.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Rotacion a la izquierda


Dado un nodo N, una Rotacion a la izquierda sobre N implica que:
El nodo N es hijo a la derecha de su padre.
El nodo N reemplara a su padre, llegando a ser hijo de su
abuelo.
El padre de N se convertira en el hijo a la izquierda de N.
El hijo a la izquierda de N se convertira en hijo a la derecha
de su antiguo padre.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Rotacion a la izquierda. Ejemplo


20
9
8 16
36
25 40
38 50
20
9
8 16
36
25 40
38 50
52
Insertar 52 arbol desequilibrado
Tras la insercion: H(36->hi)-H(36->hd)= 0-2= -2. Desequilibrio
por la derecha.
H(36->hd->hd) > H(36->hd->hi). Entonces hay desequilibrio
derecha-derecha. Se hace rotacion simple a la izquierda.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Rotacion a la izquierda. Ejemplo


40 pasa a ser hijo derecha de 20, y 20 pasa a ser padre de 40.
38 pasa a ser hijo derecha de 36, y 36 pasa a ser padre de 38.
36 pasa a ser hijo izquierda de 40, y 40 padre de 36.
20
9
8 16
40
36
38
50
52
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Rotacion izquierda-derecha. Ejemplo.


Insercion del valor 11 en el arbol:
20
15
10
40
20
15
10
11
40
Desequilibrio en 15:
H(15->hi)-H(15->hd)= 1-(-1)= 2.
(Desequilibrio izquierda)
H(15->hi->hi) < H(15->hi->hd),
-1 < 1. (Desequilibrio
izquierda-derecha)
Rotacion a la Izquierda sobre 11.
Rotacion a la Derecha sobre 11.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Rotacion izquierda-derecha. Ejemplo.


Solucion:
20
15
11
10
40
20
11
10 15
40
Rotacion izquierda en 11 Rotacion derecha en 11
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Rotacion derecha-izquierda. Ejemplo


20
9
8 16
36
25 40
50
20
9
8 16
36
25 40
50
49
Insertar 49 arbol desequilibrado
Tras la insercion: H(40->hi)-H(40->hd)= -1-1= -2. Desequilibrio
por la derecha.
H(40->hd->hd) < H(40->hd->hi). Entonces hay desequilibrio
derecha-izquierda. Se hace rotacion simple a la derecha y luego a
la izquierda.
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Rotacion derecha-izquierda. Ejemplo


20
9
8 16
36
25 40
49
50
20
9
8 16
36
25 49
40 50
Rotacion dcha. en 49 Rotacion izq. en 49
Gabriel Navarro Tema 3

Arboles

Arboles AVL: Borrado


La eliminacion de nodos en un AVL se realiza de igual forma que
en un ABB. El nodo eliminado se sustituye por:
O bien el mayor de los descendientes a la izquierda.
O bien el menor de los descendientes a la derecha.
El equilibrado comienza a realizarse desde el padre inicial del nodo
seleccionado para cubrir el hueco del nodo eliminado.
Ejercicio
Implementar la funcion de borrado en un AVL
Gabriel Navarro Tema 3

Arboles
ARBOLES PARCIALMENTE
ORDENADOS
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados y Completos


Los

Arboles Parcialmente Ordenados y Completos (APOC) son:
arboles binarios completos, es decir, tiene todos sus niveles
completos excepto el ultimo con todas sus hojas a la
izquierda, y
estan parcialmente ordenados, es decir, el valor de un nodo
siempre es menor que el de sus hijos.
Permiten recuperar el mnimo de un conjunto de forma eciente,
con complejidad O(1).
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados y Completos


Ejemplo
1
2
3
10 4
5
7
2
6 3
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados y Completos


Es una estructura de datos clasica para implementar un heap
Heap
Es una estructura de datos dise nada para almacenar un conjunto
de elementos para realizar las siguientes operaciones:
Devolver el mnimo
Borrar el mnimo
Insertar un elemento
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados y Completos


Operaciones en un APOC
El mnimo se obtiene simplemente accediendo a la raz.
La insercion de un elemento siempre se realiza lo mas a la
izquierda posible dentro del nivel de mayor profundidad y, en
caso de estar este completo, se inserta como elemento mas a
la izquierda del nivel siguiente.
El borrado se realizara unicamente en la raz
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: Insercion


Inicialmente, el elemento se inserta en el nivel mas profundo y lo mas a la
izquierda posible. Seguidamente, el arbol se reorganiza para colocar el
nodo insertado en su sitio, de modo que se cumplan los requisitos del
arbol.
La reorganizacion consiste en intercambiar el nodo introducido por su
padre hasta que, o bien el nodo sea raz, o bien el padre tenga valor
inferior al nodo.
Ejemplo:
Insertamos el valor 2
1
2
4 5
3
6
1
2
4 5
3
6 2
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: Insercion


2<3, intercambiamos. Insertamos valor 10.
1
2
4 5
2
6 3
1
2
4
10
5
2
6 3
Insertamos valor 3 3<4, intercambiamos.
1
2
4
10 3
5
2
6 3
1
2
3
10 4
5
2
6 3
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: Insercion


Insertamos valor 0. 0<5, intercambiamos.
1
2
3
10 4
5
0
2
6 3
1
2
3
10 4
0
5
2
6 3
0<2, intercambiamos. 0<1, intercambiamos.
1
0
3
10 4
2
5
2
6 3
0
1
3
10 4
2
5
2
6 3
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: borrado


En un APO, el nodo borrado del arbol se sustituye por el nodo mas a la
derecha del nivel mas profundo. Seguidamente, se reorganiza el arbol
para que se cumplan los requisitos del APO.
La reorganizacion consiste en intercambiar el nodo introducido por su
hijo de menor valor hasta que, o bien el nodo sea hoja, o bien el hijo
menos tenga valor superior al nodo.
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: borrado


Ejemplo:
Eliminamos 0 Sustituimos por 5
1
3
10 4
2
5
2
6 3
5
1
3
10 4
2
2
6 3
Hijo menor 1<5. Intercambiamos. Hijo menos 2<5. Intercambiamos.
1
2
3
10 4
5
2
6 3
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: borrado


Ejemplo:
Eliminamos 1 Sustituimos por 4
1
2
3
10 4
5
2
6 3
4
2
3
10
5
2
6 3
Hijo menor 2<4. Sustituimos. Hijo menor 3<4. Sustituimos.
2
4
3
10
5
2
6 3
2
3
4
10
5
2
6 3
Gabriel Navarro Tema 3

Arboles
APO en ordenacion: HeapSort
Los arboles APO pueden utilizarse para ordenar conjuntos de elemento,
haciendo uso de que la raz siempre sera el elemento menor del arbol.
El algoritmo HeapSort consiste en introducir todos los elementos en el
APO, e ir obteniendo y eliminando repetidamente la raz del mismo. Los
elementos se obtendran en orden creciente y con una eciencia de
O(n*log(n)).
void HeapSort(double *v, int tam){
APO<double> a;
for (int i= 0; i<tam; i++)
a.insertar(v[i]);
for (int i= 0; i<tam; i++) {
v[i]= a.getEtiqueta(a.getRaiz());
a.borrar();
}
}
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: Representacion


La forma mas simple de implementar un APOC es mediante
vectores.
Representacion
T *v; /**< vector de nodos */
int nelem; /**< N umero de nodos del arbol */
int maxelem; /**< N umero maximo de nodos del arbol */
Con esta representacion, se cumplen las siguientes propiedades:
Todo hijo a la izquierda de un nodo N se encuentra en la
componente 2*N+1
Todo hijo a la derecha de un nodo N se encuentra en la
componente 2*N+2
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: Representacion


Por tanto, los hijos a la izquierda se encontraran en las
componentes impares y los hijos a la derecha en las pares. La raz
estara en la componente 0 del vector.
Respectivamente:
Todo padre de un hijo a la izquierda N esta en la componente
(N-1)/2
Todo padre de un hijo a la derecha N esta en la componente
(N-2)/2
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: Representacion


Funcion de abstraccion
Un objeto valido rep=v,nelem,maxelem del TDA APO representa
al APO A tal que:
rep.v contiene los elementos del arbol.
rep.nelem contiene el n umero de nodos del arbol.
rep.maxelem contiene el n umero maximo de nodos del arbol.
Invariante de la Representacion
0 <= rep.nelm < rep.maxelem
rep.v apunta a una zona de memoria reservando un vector con
rep.maxelem componentes.
Para cada nodo N tal que 2*N+1=rep.nelem, rep.v[N] <
rep.v[2*N],rep.v[2*N+1]
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: Interfaz


template <class T>
class APO {
...
public:
typedef int Nodo;
APO(); APO(T valor); APO(const APO<T> &valor); APO();
Nodo getRaiz();
int getEtiqueta(Nodo n);
Nodo getPadre(Nodo n);
Nodo getHijoIzq(Nodo n);
Nodo getHijoDcha(Nodo n);
void insertar(T valor);
void borrar();
void vaciar();
bool estaVacio();
APO<T> & operator=(const APO<T> &a);
bool operator==(const APO<T> &a);
};
Gabriel Navarro Tema 3

Arboles

Arboles Parcialmente Ordenados: Representacion


Ver Especicacion Completa
Ver Implementacion Completa
Gabriel Navarro Tema 3

Arboles
ARBOLES N-ARIOS
Gabriel Navarro Tema 3

Arboles

Arboles n-arios
Son arboles con nodos cuyo n umero de hijos no esta limitado a
priori.
Por tanto, no procede hablar de Hijo a la Izquierda e Hijo a la
Derecha. En su lugar hablaremos de:
Hijo a la Izquierda: El hijo de un nodo situado mas a la
izquierda.
Hermano a la Derecha: El hijo de un nodo que esta situado
justo a la derecha de otro nodo hijo del mismo.
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Ejemplo


A
B
E
F G
H Q
J K
I
C D
L M N
O P
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Implementaciones


Al igual que en los TDAs estudiados con anterioridad, la forma de
implementar un arbol n-ario dependera del problema a resolver y
de la capacidad del dise nador. No obstante, existen 3
implementaciones basicas:
Implementacion matricial. El arbol se representa en un vector
de enteros, donde cada componente contiene el ndice de su
nodo padre.
Implementacion con listas. Se representa mediante un vector
de listas. Cada ndice de las componentes del vector se asocia
con un nodo del arbol, y cada componente es una lista con los
hijos del nodo.
Implementacion con celdas enlazadas. Cada nodo del arbol es
una celda enlazada con un puntero a su padre, a su hijo
izquierda y a su hermano derecha.
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Implementacion matricial


El tipo Nodo del arbol es entero.
La relacion padre-hijo se representa en un vector P, donde P[i]
indica cual es el nodo padre de i. Si el nodo no tiene padre
(es la raz), P[i] tomara valor -1.
Las etiquetas de los nodos se representan en otro vector de
etiquetas.
Esta implementacion es relativamente sencilla y con bajo coste de
memoria. Facilita las operaciones de acceso a los ancestros de un
nodo (eciencia O(log(n)) para viajar desde un nodo hoja hasta la
raz), pero resulta difcil gestionar operaciones con los hijos
(conocer la altura, determinar los hijos, establecer hijo izquierda y
hermano derecha...).
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Implementacion matricial. Ejemplo


1
2
5 4 3
6
7 8
9 0
P=
8
0
-1
1
raiz
1
2
2
3
2
4
2
5
1
6
6
7
6
8
8
9
Etiquetas=
0 1 2 3 4 5 6 7 8 9
En el ejemplo, resulta
difcil hallar que 5 es hijo
a la izquierda de 2. Para
solucionar este problema
sera necesario establecer
un orden entre los nodos.
Esto puede
implementarse
directamente sobre el
vector, o incluyendo
otros tipos de datos (por
ejemplo, otro vector de
hijos izquierda).
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Implementacion con listas


El arbol se representa en un vector de listas. Cada ndice de la
componente del vector se asocia a un nodo, y cada componentes
es una lista de enteros con los ndices de sus nodos hijos.
El problema es determinar cual nodo es el raz. Para ello, usaremos
una variable raiz que apunte al nodo del arbol.
Pueden incluirse las etiquetas de los nodos en un vector adicional.
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Implementacion con listas. Ejemplo


0 X
1 2 6 X
2 5 4 3 X
3 X
4 X
5 X
6 7 8 X
7 X
8 9 0 X
9 X
raiz= 1;
1
2
5 4 3
6
7 8
9 0
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Implementacion con listas


La implementacion de arboles con listas, al contrario que la
matricial, diculta el acceso a los padres de un nodo y operaciones
asociadas con el mismo.
Por ejemplo: obtener la profundidad de un nodo es O(n).
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Implementacion con celdas enlazadas


Un nodo del arbol sera una celda reservada con memoria dinamica,
conteniendo los campos siguientes:
Puntero al nodo padre.
Puntero al nodo hijo a la izquierda.
Puntero al nodo hermano a la derecha.
Etiqueta.
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Implementacion con celdas enlazadas


Celda de un arbol n-ario:
template <class Elemento>
class Arbol {
...
public:
class Celda {
private:
Elemento et;
Celda *padre;
Celda *hijoi; // Hijo a la izquierda
Celda *herd; // Hermano a la derecha
public:
...
friend class Arbol; // Para permitir al arbol acceder a los atributos
};
typedef Celda * Nodo;
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Representacion con celdas enlazadas


Representacion del arbol
Celda *raiz; /**< Nodo raz del arbol */
Funcion de Abstraccion
Dado el tipo representado rep={raiz}, el objeto al que representa
es un arbol L tal que raiz es la raz del arbol, y para cualquier nodo
N, N->padre contiene el padre de N, N->hijoi contiene su hijo
izquierdo y N->herd contiene su hermano a la derecha.
Recursivamente N->hijoi y N->herd seran a su vez subarboles del
arbol original.
Invariante de la Representacion
rep.raiz es null. En caso contrario, rep.raiz->padre y rep.raiz->herd
es null. Para todo nodo del arbol N, N->hijoi apunta a su hijo
izquierdo, o vale null en caso de no tener. N->herd apunta a su
hermano derecho, o vale null en caso de no tener.
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Interfaz


template <class T>
class Arbol {
public:
Arbol();
Arbol( T valor);
Arbol(const Arbol<T> & a);
Arbol();
void setRaiz(T valor);
Nodo getRaiz();
T getEtiqueta(Nodo n) const;
void setEtiqueta(Nodo &n, T valor);
...
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Interfaz


...
Nodo getPadre(Nodo n);
Nodo getHijoIzq(Nodo n);
Nodo getHermanoDcha(Nodo n);
Nodo getHermanoIzq(Nodo n);
void insertarHijoIzq(Nodo &p, T valor);
void insertarHermanoDcha(Nodo &p, T valor);
void podar(Nodo &n);
void vaciar();
bool estaVacio() const;
Arbol<T> & operator= (const Arbol<T> &a);
bool operator== (const Arbol<T> &a) const;
};
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Interfaz


Lo mas relevante:
Insercion de hijos y hermanos.
Poda.
Copia de arboles.
Ver Especicacion Completa
Ver Implementacion Completa
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Insercion de hijos a la izquierda


La insercion de un hijo a la izquierda supone realizar las siguientes
acciones:
1 Crear una nueva celda aux.
2 Si el nodo N->hijoi != 0, desplazar N->hijoi como hermano a la
derecha de aux, haciendo aux->herd= N->hijoi.
3 Asignar N->hijoi= aux y N->hijoi->padre= N.
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Insercion de hermanos a la derecha


La insercion del hermano a la derecha de un nodo N supone realizar las
siguientes acciones:
1 Crear una nueva celda aux.
2 Asignar el hermano a la derecha de N como hermano a la derecha
de aux: aux->herd= N->herd
3 Asignar aux como nuevo hermano a la derecha de N: N->herd= aux
4 Asignar el padre de aux como el padre de N: aux->padre=
N->padre
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Poda de nodos


La poda de un nodo N supone eliminar N y todos sus descendientes,
reasignar sus hermanos (a la izquierda y a la derecha) y, en caso de ser
hijo a la izquierda, modicar el padre:
1 Si el nodo N a eliminar es nulo, salir.
2 Mientras N tenga hijos a la izquierda, podar(N->hijoi)
3 Asignar aux= hermano a la izquierda de N
4 Si N es nulo, entonces hacer N->padre->hijoi= 0
5 En otro caso, reasignar hermano a la derecha del hermano a la
izquierda de N: aux->herd= N->herd
6 Eliminar nodo N
Gabriel Navarro Tema 3

Arboles

Arboles n-arios: Copiar subarboles


La copia de un subarbol con nodo raz orig en otro con nodo raz dest
supone que inicialmente dest es un subarbol vaco. Para copiar orig en
dest, realizaremos las siguientes acciones:
1 Crear la nueva celda dest y asignarle el valor de orig->valor -
2 Llamar recursivamente a CopiarNodos de orig->hijoi en dest->hijoi.
Si la copia del hijo izquierdo no es nulo, asignar
dest->hijoi->padre= dest
3 Copiar recursivamente los hermanos a la derecha de orig->hijoi, de
igual forma a como se ha copiado el hijo a la izquierda.
Gabriel Navarro Tema 3

Arboles

También podría gustarte