Está en la página 1de 39

ARBOLES

ESTRUCTURAS DE DATOS
www.espol.edu.ec
www.fiec.espol.edu.ec
INTRODUCCION
¨ Las listas enlazadas son estructuras lineales
a Son flexibles pero son secuenciales, un elemento detrás de otro
r Los árboles
r Junto con los grafos son estructuras de datos no lineales
a Superan las desventajas de las listas
e Sus elementos se pueden recorrer de distintas formas, no
necesariamente uno detrás de otro
n Son muy útiles para la búsqueda y recuperación de
información
A es Padre
B y C hijos de A:

CONCEPTO hermanos
B es Padre
D, E, F hijos de B
A
Ì Estructura que organiza sus elementos formando
jerarquías: PADRES E HIJOS
o Los elementos de un árbol se llaman nodos
B C
l Si un nodo p tiene un enlace con un nodo m,
p es el padre y m es el hijo D E F
Los hijos de un mismo padre se llaman: hermanos
Todos los nodos tienen al menos un padre, menos la raíz: A
t Si no tienen hijos se llaman hoja: D, E, F y C
B
E Un subárbol de un árbol
n Es cualquier nodo del árbol junto con todos sus
descendientes D E F
TERMINOLOGIA
L Camino: Secuencia de nodos conectados dentro de un arbol
n Longitud del camino: es el numero de nodos menos 1 en un camino
e Altura del árbol: es el nivel mas alto del árbol
s Un árbol con un solo nodo tiene altura 1
s Nivel(profundidad) de un nodo: es el numero de nodos entre el nodo
y la raíz.
e Nivel de un árbol
l Es el numero de nodos entre la raíz y el nodo mas profundo del árbol, la altura
del un árbol entonces
o Grado(aridad) de un nodo: es numero de hijos del nodo
i Grado(aridad) de un árbol: máxima aridad de sus nodos
TDA ARBOL : DEFINICION
INFORMAL
N Valores:
S Conjunto de elementos, donde SOLO se conoce el nodo raíz
d Un nodo puede almacenar contenido y estar enlazado con
m Sus árboles hijos (pueden ser dos o varios)
s Operaciones: Dependen del tipo de árbol, pero en general tenemos
e Vaciar o inicializar el Arbol
i void Arbol_Vaciar (Arbol *A);
r Eliminar un árbol
l void Arbol_Eliminar(Arbol *A);
n Saber si un árbol esta vacío
l bool Arbol_EstaVacio(Arbol A);
a Recorrer un árbol
l void PreOrden(Arbol A)
b void EnOrden(Arbol A)
o void PostOrden(Arbol A)
TDA ARBOL: DEFINICION
FORMAL

<arbol> ::= <<NULL>> | <nodo>


<nodo> ::= <contenido>{<arbol>}
<contenido> ::= <<dato>>{<<dato>>}
ARBOLES BINARIOS A

B C
ˆ Tipo especial de árbol
D
Cada nodo no puede tener mas de dos hijos
d Un árbol puede ser un conjunto RAIZ
e Vacío, no tiene ningún nodo
A
n O constar de tres partes:
B C
s Un nodo raíz y
( Dos subárboles binarios: izquierdo y derecho D E F G

i La definición de un árbol binario es recursiva H I J


La definición global depende de si misma Sub. Izq. Sub. Der.
DEFINICIONES RECURSIVAS SUB. DER.
U La definición del árbol es recursiva A
Nivel 1

l Se basa en si misma B C
s La terminología de los árboles D
d También puede ser definida en forma recursiva
E
r Ejemplo: NIVEL de un árbol
e Identificar el caso recursivo y el caso mas básico
SUB. IZQ.
SUB.
SUB. IZQ.
nivel 1 S. izq. A S. der. Nivel =
= 31 DER..
NivelSUB. +
A Nivel 1 Nivel 1 Max(0,2) +
Nivel = 1
Max(0,Sub.Izq)
B C Nivel = 1
Max(0,Sub.Izq.)
Max(0,1)

Nivel Del Arbol: 2


Caso Básico NIVEL
NIVEL : MAX(S.IZQ,
1 + MAX(3,
: 1 +NIVEL :4 1)
S.DER)

Un árbol con un solo Caso Recursivo


nodo tiene nivel 1 Si tiene mas de un nodo, el nivel es:
1 + MAX(Nivel(SubIzq), Nivel(SubDer))
ARBOLES BINARIOS LLENOS
Un árbol de altura h, esta lleno si
r Todas sus hojas esta en el nivel h
e Los nodos de altura menor a h tienen siempre 2 hijos
u Recursiva
u Si T esta vacío,
Entonces T es un árbol binario lleno de altura 0
Si no esta vacío, y tiene h>0
, Esta lleno si los subárboles de la raíz, son ambos árboles
binarios llenos de altura h-1
ARBOLES BINARIOS
COMPLETOS
Un arbol de altura h esta completo si
r Todos los nodos hasta el nivel h-2 tienen
dos hijos cada uno y
n En el nivel h-1, si un nodo tiene un hijo
derecho, todas las hojas de su subarbol
izquierdo están a nivel h
a Si un arbol esta lleno, tambien esta
completo
OTROS
L Un árbol equilibrado es cuando
r La diferencia de altura entre los subárboles de cualquier nodo es
máximo 1
Un árbol binario equilibrado totalmente
Los subárboles izquierdo y derecho de cada nodo tienen las
misma altura: es un árbol lleno
Un árbol completo es equilibrado
o Un árbol lleno es totalmente equilibrado
RECORRIDOS DE UN A.B.
Recorrer es
p Visitar todos los elementos de una estructura
s Como recorrer un árbol
Hay tantos caminos, cual escoger?
o Existe tres recorridos típicos
r Nombrados de acuerdo a la posición de la raíz
e Preorden: raíz - subarbol izq. - subarbol der.
Enorden : subarbol izq. - raíz - subarbol der.
o Postorden : subarbol izq. - subarbol der. -raíz
1. Visitar raiz
2. Preorden al Subarbol Izq.
3. Preorden al Subarbol Der.

EJEMPLO PREORDEN
G
1
D K
2 8
B E H M
3 6 9 12
A C F J L
4 5 7 10 13

I
11

G-D
G-D-B-A-C-E
G-D-B-A-C
G-D-B-A
G-D-B
G-D-B-A-C-E-F
G-D-B-A-C-E-F-K
G-D-B-A-C-E-F-K-H
G-D-B-A-C-E-F-K-H-J
G-D-B-A-C-E-F-K-H-J-I
G-D-B-A-C-E-F-K-H-J-I-M
G-D-B-A-C-E-F-K-H-J-I-M-L
AB y NODOAB: DEFINICION
FORMAL
<ab>::= nulo | <nodo>
<nodoab>::=<contenido>+<izq>+<der>
<izq>::=<ab>
<der>::=<ab>
<contenido>::<<dato>>|{<<dato>>}
AB Y NODOAB:
DECLARACION
Ì Un árbol binario: conjunto de nodos
typedef struct NodoAB{
: Solo se necesita conocer el nodo raíz Generico G;
NodoAB *izq, *der;
Cada nodo }NodoAB;
Tiene Contenido y
y Dos enlaces: árbol hijo izquierdo, árbol hijo derecho
o Un nodo hoja, es aquel cuyos dos enlaces apunta a null
Un nodo en un árbol tiene mas punteros a null que un nodo de una lista
b De un árbol solo se necesita conocer su raíz
La raíz, que es un nodo, puede definir al árbol o

typedef struct NodoAB *AB;


NODOAB: OPERACIONES
L Elemento de un árbol que
r Almacena información (contenido),
c Conoce hijo izq. y derecho, ambos son nodos
Operaciones Básicas
c Crear un nuevo nodo hoja y eliminar hoja existente
o NodoAB *NodoAB_CrearHoja(Generico G);
r void NodoAB_Eliminar (NodoArbol **A);
i Saber si el nodo es o no hoja
bool NodoAB_EsHoja(NodoArbol *p);
NODOAB: MAS
OPERACIONES
P Consultas de los campos de un nodo
Generico NodoAB_ConsultaContenido(NodoAB *nodo);
C NodoAB *NodoAB_Izq (NodoAB *nodo);
z NodoAB *NodoAB_Der(NodoAB *nodo);
e Cambiar los campos de un nodo
o void NodoAB_SetContenido (NodoAB *nodo , Generico G);
o void NodoAB_SetIzq(NodoAB *nodo, NodoAB *enlace);
z void NodoAB_SetDer(NodoAB *nodo, NodoAB *enlace);
AB: CREAR NODO HOJA
O Se debe crear un nodo nuevito: un nodo hoja

NodoAB *NuevaHoja(Generico G){


NodoAB *nuevo;
nuevo = (NodoAB *)malloc(sizeof(NodoAB));
nuevo->G = G;
nuevo->izq = NULL;
nuevo->der= NULL;
return nuevo;
}
AB: OPERACIONES
l Crear y Eliminar
l AB_Vaciar(AB *A);
; AB_Eliminar(AB *A);
A Estado del Arbol
D bool AB_EstaVacio(AB A);
o Añadir y remover nodos
void AB_InsertarNodo(AB *A, NodoAB *nuevo)
N NodoAB *AB_SacarNodoxContenido(AB *A, Generico G, Generico_fnComparar fn);
N NodoAB * AB_SacarNodoxPos(AB *A, NodoAB *pos);
r Busqueda por contenido
t NodoArbol *AB_Buscar(AB A, Generico G, Generico_fnComparar fn );
s Recorridos
+ void AB_PreOrden(AB A);
( void AB_PosOrden(ABl A);
( void AB_EnOrden(AB A);
AB: INSTANCIANDO Y CREANDO
Un Arbol Vacío, es aquel cuyo nodo raíz apunta a NULL
void AB_Vaciar(AB *A){
*A = NULL;
}

B Para crear una variable tipo Arbol, y empezarla a usar:


a Instanciarlo (crear variable) AB A;
e Vaciar el árbol AB_Vaciar(&A);
e Para añadirle una hoja al árbol, crear hoja: A
A = NodoAB_CrearHoja(Generico_CrearEntero(1));
1
RECORRIDOS:
IMPLEMENTACION
ì Como ya revisamos, las operaciones de recorrido son recursivas
s Ejemplo: EnOrden
s Recorrer EnOrden al subarbol izquierdo
Visitar nodo raiz
z Recorrer EnOrden al subarbol derecho
En todo algoritmo recursivo debemos buscar dos casos
o Básico, para terminar la recursividad
m Recursivo, donde la función se llama a si misma
Caso Recursivo
Caso Básico
Si !AB_EstaVacio(raiz)
Si AB_EstaVacio(raiz)
( AB_EnOrden(raiz->izq);
r Terminar de recorrer
> Mostrar raiz->I
> AB_EnOrden(raiz->der);
OPERACION ENORDEN
void AB_EnOrden(AB A, Generico_fnImprimir imprimir){
if(!AB_EstaVacio(A)){
AB_EnOrden(A->izq,imprimir);
imprimir(A->G);
AB_EnOrden(A->der,imprimir);
}
}

Arbol 4
ArbolVacio!,
Vacio!,Terminar
Terminar
B C

2 6
D E F G

Arbol Vacio!, Terminar 1 3 5 7


APLICACIÓN: EVALUACION
DE EXPRESIONES
U Ya sabemos lo de las expresiones, cierto?
InFija, operador en medio
PreFija, operador antes de dos operandos
r PosFija, operador luego de dos operandos
r Para evaluar una expresion dada, podriamos
Pasarla a posfija y usar solo pilas
a Pasarla a posfija y usar pilas y un arbol de expresion
ARBOL DE EXPRESION
O Arboles que representan expresiones en memoria
e Todos los operadores tienen dos operandos
o La raiz puede contener el operador
n Hijo izq: operando 1, Hijo derecho: operando 2
d Ejemplo: (a+b) (a+b)*c
*
+
+ c
a b
a b
EJERCICIO EN CLASE
S Construya arboles de expresion para:
s [X+(Y*Z)] * (A-B)
) Deducir las expresiones de los siguientes A.B.
+

a *

b -

c d
EVALUAR UNA EXPRESION
ARTIMETICA EN INFIJA
F La expresion se transforma a la expresion posfija
t Esto, ya sabemos como hacer
Crear un arbol de expresion
e Para esto se va a usar una pila y un arbol de caracteres
a Usando el arbol, evaluar la expresion
CREAR UN ARBOL DE
EXPRESION
E Los operandos seran siempre nodos hoja del arbol
r Al revisar un operando, creo una nueva hoja y la recuerdo
e Los operadores seran nodos padre
e Al revisar un operador, recuerdo las dos ultimas hojas creadas y uno todo
e No debo olvidar el nuevo arbolito que he creado

A*B-C*D+H AB*CD*-H+ +

- H

D * *
-
C * A B C D
H *
B *
* C D
A A B C D
A B
EVALUACION DE LA EXP.
POSTFIJA
Lo ideal es recuperar los dos operandos, el operador, y ejecutar la opcion
p Que recorrido es el ideal?
Para evaluar el arbol:
PostOrden
Si el arbol tiene un solo nodo y este almacena un
operando
El resultado de la evaluacion es el valor de ese
operando
+
Si no
- H 1. Res1 = Evaluo subarbol izquierdo

* * 2. Res2 = Evaluo subarbol derecho

B 3. Recupero la info de la raiz y efectuo la


A C D
operación alli indicada, entre Res1 y Res2

A*
(Ay*BB) -y (C*D)
CyD+
(C*D) y HH
ARBOL BINARIO DE <>

BUSQUEDA 55

30 75
Los elementos en un arbol
Hasta ahora no han guardado un orden 4 41 85
a No sirven para buscar elementos
u Los arboles de busqueda
u Permiten ejecutar en ellos busqueda binaria <>
r Dado un nodo:
6
r Todos los nodos del sub. Izq. Tienen una clave menor que
la clave de la raiz 4 9
a Todos los nodos del sub. Der. Tienen una clave mayor que
la clave de la raiz 5
TDA ABB: DEFINICION
<abb>::= NULL | <abb_nodo>
<abb_nodo>::=<clave>+<contenido>+<izq>+<der>
<izq>::=<abb>
<der>::=<abb>
I Valores: <clave>::<<dato>>|{<<dato>>}
E Conjunto de elementos <contenido>::<<dato>>|{<<dato>>}
e Dado un nodo p,
e Los nodos del arbol izquierdo almacenan valores mayores al de p
b Los nodos del arbol derecho almacenan valores menores al de p

b Operaciones
A Son las mismas operaciones que para un AB
p Pero en este caso ya tenemos reglas suficientes que nos indican como:
o Insertar
I Sacar y typedef struct ABB_Nodo{
Generico clave, G;
I Buscar
ABB_Nodo *izq, *der;
}ABB_Nodo;
CREAR CON CLAVE
Ð Como el nodo ahora tiene un campo clave
r Cambian un poco las operaciones del nodo
l Ejemplo
NodoAB *NuevaHoja(Generico clave, Generico contenido){
NodoArbol *nuevo;
nuevo = malloc(sizeof(NodoArbol));
nuevo->clave = clave;
nuevo->G = contenido;
nuevo->izq = NULL;
nuevo->der= NULL;
return nuevo;
}
CREACION DE UN ABB
B Un arbol de busqueda debe mantener
u A la derecha mayor a raiz
o A la izq. Menor a raiz
a Ejemplo:
a Construya arbol con los siguientes elementos:
c 8, 3, 1, 20, 10, 5, 4

3 20

1 5 10

4
EJERCICIO EN CLASE
S Construya el arbol para almacenar:
o 12, 8, 7, 16, 11
BUSQUEDA DE UN NODO
O Dada una clave, devolver el nodo que la contiene
d Se comienza en la raiz
a Si el arbol esta vacio
No se encontro
Buscar(raiz,25)
Buscar(raiz,5)
o Si clave buscada es igual a la clave del nodo evaluado
BINGO, LO ENCONTRE
R Si no
8
} Si la clave buscada es mayor a la del nodo evaluado
a Buscar en el subarbol derecho
3 20
a Si no
c Buscar en el subarbol izquierdo
1 5 10

4 No existe
IMPLEMENTACION DE LA
BUSQUEDA
NodoABB *ABB_Buscar(ABB A, Generico clave, Generico_fnComparar comp){
if(ABB_EstaVacio(A)) return NULL;
if(f(clave, A->clave) == 0) return A;
if(f(clave, A->clave) > 0))
return ABB_Buscar(A->der, clave, comp);
else
return ABB_Buscar(A->izq, clave, comp);
}
INSERCION DE UN NODO
N Muy parecido a la busqueda Insertar(raiz,15)
a Debo insertar en la posicion correcta 15>8…der

El arbol debe mantener sus propiedades 8


15<20…
izq

n Pasos: 3
15>10
…der 20
n Crear una nueva hoja 1 5 10 Insertar
aqui
h Buscar en el arbol donde ponerla 4
15
o Enlazar el nuevo nodo al arbol
IMPLEMENTACION DE LA
INSERCION
bool ABB_Insertar(ABB *A, NodoABB *nuevo, Generico_fnComparar f){
if(!ABB_EstaVacio(*A)){
if(f(nuevo->clave, (*A)->clave) >0)
ABB_Insertar((*A)->der, nuevo,f);
else if(f(nuevo->clave, (*A)->clave) <0)
ABB_Insertar((*A)->izq,nuevo,f);
else
return FALSE;
} else{
//Si esta vacio, alli insertar
*A = nuevo;
}
return TRUE;
}
ELIMINACION DE UN
NODO
Eliminar(raiz,34)
N Es mas compleja que la insercion
q Al sacar un nodo del arbol 34
28
El arbol debe mantener sus propiedades 18 90
n El arbol debe reajustarse
6 25 100
a Pasos:
a Buscar el nodo p que se va a eliminar 20 28
m Si el nodo a eliminar tiene menos de dos hijos
nmayor
m Subir el nodo hijo a la pos. del nodo eliminado
j Si no
e Ubicar el nodo q con la mayor de las claves menores
l Reemplazar contenido de p con el del nodo q
Eliminar el nodo q que se encontro el el primer paso
SACAR NODO: CODIGO
NodoABB *ABB_SacarNodoxContenido(ABB *A, Generico clave,
Generico_fnComparar fn){
NodoABB *p, *tmp = *A;
if(ABB_EstaVacio(*A)) return NULL;
if(fn((*A)->clave, clave) < 0)
return(ABB_SacarNodoxContenido(&(*A)->der, clave, fn));
else if(fn((*A)->clave, clave) >0)
return(ABB_SacarNodoxContenido(&(*A)->izq, clave, fn));

if((*A)->der == NULL)
(*A) = (*A)->izq;
else if((*A)->izq == NULL)
(*A) = (*A)->der;
else
tmp = ABB_SacarRaiz(A);
return tmp;
}

También podría gustarte