You are on page 1of 10

Arboles

Estructura de Arbol.
Un árbol es otra clase de estructura de datos que puede
definirse como: Una estructura de árbol como tipo Base T
es:
• Una estructura vacia
• Una estructura T ligada con un número finito de
estructuras de árbol disjuntas asociadas de tipo base T,
llamadas subárboles.

Un árbol se puede representar de diferentes formas:

K O F H
I J E P
D L M N
B G C
A

Conjuntos anidados
(A(B(D(I),E(J,K,L), C (F(O),G(M,N),H(P) ) ) )

Paréntesis anidados

B C

D E F G H

I J K L O M N P
Gráfica
La raíz de un árbol es el nodo superior y tiene nivel 0. Un
nodo Y que esta directamente debajo de otro nodo X, se
llama descendiente o hijo de X. Si un nodo no tiene
descendientes se llama nodo terminal u hoja. Un nodo no
terminal se llama nodo interior. El grado de nodo es igual al
número de descendientes.

Si, X está en el nivel i, y Y es hijo de X, entonces Y está en


el nivel i+1. El nivel máximo de un árbol es su profundidad o
altura. El número de ramas o aristas que tiene que ser
recorridas desde la raíz hasta un nodo x se llama longitud
de trayectoria de x. La longitud de trayectoria de un árbol es
la suma de las longitudes de trayectoria de todos sus
componentes.

Un árbol es perfectamente balanceado, si para cada nodo


los números de nodos de sus subárboles izquierdo y
derecho difieren cuando más en 1.

Los árboles de grado 2 son un caso particular, llamados


árboles binarios. Un árbol binario ordenado se define como
un conjunto de nodos finito de elementos que es vacío o
consta de una raíz con dos subárboles binarios disjuntos
llamados subárbol izquierdo y derecho de la raíz. Los
árboles de grado mayor a 2 se llama árboles multicamino o
multimodales.

La representación de un árbol puede ser:


NULL para un árbol vacío
o
class NodoArbol{
NodoArbol nodoIzquierdo;
int datos;
NodoArbol nodoDerecho;
………….
}
Las operaciones que se realizan con estructuras de árbol,
son más complejas que las listas. Las principales
operaciones sobre árboles son:

• Inserción de un nuevo nodo.


• Eliminación o borrado de un nodo.
• Recorrido de un árbol
o En preorden
o En orden
o En postorde
• Búsqueda de un elemento.
• Balanceo del árbol.

Los árboles binarios se usan para representar un conjunto


de datos cuyos elementos se recuperan a través de una
llave única.

Creación del árbol.


La construcción de un árbol se puede hacer bajo dos
criterios:

• Insertando los nuevos nodos dependiendo de la llave.


• Creando un árbol balanceado.

Inserción en un árbol de búsqueda.

Un árbol de búsqueda es aquel que se organiza de tal


forma que para cada nodo ti todas las llaves en el subárbol
izquierdo de ti sean menores que la llave de ti y aquellas en
el subárbol derecho sean mayores que la llave de ti.

En un árbol de búsqueda es posible localizar una llave


comenzando la búsqueda en la raíz y siguiendo una
trayectoria de búsqueda seleccionando un subárbol
izquierdo o derecho por una decisión basada en la
inspección de la llave del nodo.
class NodoArbol{
NodoArbol nodoIzquierdo;
int datos;
NodoArbol nodoDerecho;

public NodoArbol(int datosNodo){


datos=datosNodo;
nodoIzquierdo=nodoDerecho=null;
}

public void insertar(int valorInsertar){

//inserta en subarbol izq.


if(valorInsertar<datos){
//inserta nuevo NodoArbol
if(nodoIzquierdo==null)
nodoIzquierdo=new
NodoArbol(valorInsertar);
else //continuar recorriendo el subárbol izq.
nodoIzquierdo.insertar(valorInsertar);
}

//insertar en subárbol der.


else if(valorInsertar>datos){
//insertar nuevo NodoArbol
if(nodoDerecho==null)
nodoDerecho=new
NodoArbol(valorInsertar);
else //continuar recorriendo subárbol der.
nodoDerecho.insertar(valorInsertar);
}
}//fin de método insertar
}//fin se la clase Nodoarbol
Recorridos del árbol.
Existen tres ordenamientos naturales que surgen de las
estructuras de árbol y que se expresan al igual que la
definición del árbol, en términos recursivos:
1. Preorden (Visitar la raíz, subárbol izquierdo, subárbol
derecho.
2. En orden (Visitar subárbol izquierdo, raíz, subárbol
derecho)
3. Postorden (Visitar subárbol izquierdo, subárbol derecho,
raíz)

//método recursivo para realizar recorrido preorden


public void ayudantePreorden(NodoArbol nodo){
if(nodo==null)
return;
System.out.print(nodo.datos+" "); //mostrar datos del nodo
ayudantePreorden(nodo.nodoIzquierdo); //recorrer subárbol izq.
ayudantePreorden(nodo.nodoDerecho); //recorrer subárbol der.
}

//método recursivo para realizar recorrido inorden


public void ayudanteInorden(NodoArbol nodo){
if(nodo==null)
return;
ayudanteInorden(nodo.nodoIzquierdo); //recorrer subárbol izq.
System.out.print(nodo.datos+" "); //mostrar datos del nodo
ayudanteInorden(nodo.nodoDerecho); //recorrer subárbol der.
}

//método recursivo para realizar recorrido postorden


public void ayudantePostorden(NodoArbol nodo){
if(nodo==null)
return;
ayudantePostorden(nodo.nodoIzquierdo); //recorrer subárbol izq.
ayudantePostorden(nodo.nodoDerecho); //recorrer subárbol der.
System.out.print(nodo.datos+" "); //mostrar datos del nodo
}
Borrado en árboles.
Se pueden presentar tres casos diferentes al borrar un
nodo:
• No hay ningún nodo con clave igual a x.
• El nodo con clave x no tiene descendientes.
• El nodo con clave x tiene un único descendiente.
• El nodo con clave x tiene dos descendientes.

Si elemento a borrar es un nodo terminal o tiene un


descendiente la tarea es fácil. El problema está en el
borrado de un elemento que tiene dos descendientes.

void borrar(int x, nodo **p)


{ nodo *q;
void bor(nodo **r,nodo **p);
if (*p==NULL) printf("\nLa clave a borrar no existe");
else
if(x < (*p)->clave)
{ borrar (x, &(*p)->iz);}
else if (x > (*p)->clave)
{borrar(x,&(*p)->de);}
else
{ q=*p;
if ((*p)->de==NULL)
*p=q->iz;
else if((*p)->iz==NULL)
*p=q->de;
else bor(&(*p)->iz,&(*p));
}
}
void bor(nodo **r,nodo **p)
{ if ((*r)->de!=NULL)
bor(&(*r)->de,&(*p));
else { (*p)->clave=(*r)->clave;
*r=(*r)->iz;}
}
Balanceo de un árbol.
La creación de un árbol de búsqueda, en el cual los nodos
son insertados dependiendo de la clave puede dar un árbol
desbalanceado.

Por ejemplo para la siguiente secuencia:


5 8 10 15 25

10

15

25

El árbol resultante es un árbol en el que el peso recae sobre


el subárbol derecho. También puede verse como una lista
con apuntadores adicionales a nulo.
Mantener un árbol perfectamente balanceado no es muy
rentable. Se puede entonces considerar definiciones menos
estrictas sobre el balanceo de árboles como la siguiente:
Un árbol está balanceado si y sólo si en cada nodo las
alturas de sus subárboles difieren a lo máximo en 1.
Estos árboles reciben el nombre de árboles AVL(en honor
a sus inventores Adelson-Velski y Landis).

El peso de un árbol binario es el nivel máximo de sus hojas.

Balance de =Peso del subárbol izq - Peso del subárbol der


un nodo
3-4

1 0

0 1-1 0 1 -1

Un árbol está balanceado si para cualquiera de sus nodos


se tiene balance 1,0 ,-1.

Balance de un nodo.
-1 Cargado a la derecha
1 Cargado a la derecha
0 Balanceado
C Crítico

Para mantener un árbol balanceado es necesario realizar


una transformación (rotaciones)sobre el árbol de forma que:

1. El recorrido ENORDEN el árbol transformado sea el


mismo que para el árbol original.
2. El árbol transformado está balanceado.

Las operaciones de inserción y borrado de nodos en un


árbol de búsqueda pueden producir árboles
desbalanceados.
Rotaciones:
Rotación a la izquierda de un nodo p.
Rotación a la derecha de un nodo p.

F p

q B I ------q

A h---- C G --------h J

Rotación a la derecha
B qizq(p)
hder(q)
der(q)p
A F izq(p)h

C I

G J

Rotación a la izquierda
I

F J
B G qder(p)
hizq(q)
Izq(q)p
A C der(p)h

2 Nodo crítico

1 5

4 6

You might also like