Sei sulla pagina 1di 39

ARBOLES

ESTRUCTURAS DE DATOS

INTRODUCCION

Las listas enlazadas son estructuras lineales

Son flexibles pero son secuenciales, un elemento detrs de otro

Los rboles

Junto con los grafos son estructuras de datos no lineales

Superan las desventajas de las listas

Sus elementos se pueden recorrer de distintas formas, no


necesariamente uno detrs de otro

Son muy tiles para la bsqueda y recuperacin de


informacin

CONCEPTO

A es Padre
B y C hijos de A:
hermanos
B es Padre
D, E, F hijos de B

Estructura que organiza sus elementos formando


jerarquas: PADRES E HIJOS

Los elementos de un rbol se llaman nodos

Si un nodo p tiene un enlace con un nodo m,

p es el padre y m es el hijo

Los hijos de un mismo padre se llaman: hermanos

B
D

Todos los nodos tienen al menos un padre, menos la raz: A

Si no tienen hijos se llaman hoja: D, E, F y C

Un subrbol de un rbol

Es cualquier nodo del rbol junto con todos sus


descendientes

A
C

TERMINOLOGIA

Camino: Secuencia de nodos conectados dentro de un arbol


Longitud del camino: es el numero de nodos menos 1 en un camino
Altura del rbol: es el nivel mas alto del rbol

Nivel(profundidad) de un nodo: es el numero de nodos entre el nodo


y la raz.
Nivel de un rbol

Un rbol con un solo nodo tiene altura 1

Es el numero de nodos entre la raz y el nodo mas profundo del rbol, la altura
del un rbol entonces

Grado(aridad) de un nodo: es numero de hijos del nodo


Grado(aridad) de un rbol: mxima aridad de sus nodos

TDA ARBOL : DEFINICION


INFORMAL

Valores:
Conjunto de elementos, donde SOLO se conoce el nodo raz
Un nodo puede almacenar contenido y estar enlazado con

Sus rboles hijos (pueden ser dos o varios)

Operaciones: Dependen del tipo de rbol, pero en general tenemos

Vaciar o inicializar el Arbol

Eliminar un rbol

void Arbol_Eliminar(Arbol *A);

Saber si un rbol esta vaco

void Arbol_Vaciar (Arbol *A);

bool Arbol_EstaVacio(Arbol A);

Recorrer un rbol
void PreOrden(Arbol A)
void EnOrden(Arbol A)
void PostOrden(Arbol A)

TDA ARBOL: DEFINICION


FORMAL
<arbol> ::= <<NULL>> | <nodo>
<nodo> ::= <contenido>{<arbol>}
<contenido> ::= <<dato>>{<<dato>>}

ARBOLES BINARIOS

Tipo especial de rbol

Cada nodo no puede tener mas de dos hijos

Un rbol puede ser un conjunto

Vaco, no tiene ningn nodo

O constar de tres partes:

Un nodo raz y

Dos subrboles binarios: izquierdo y derecho

La definicin de un rbol binario es recursiva

La definicin global depende de si misma

RAIZ

A
B
D
H

C
E

Sub. Izq.

G
J

Sub. Der.

DEFINICIONES RECURSIVAS

La definicin del rbol es recursiva

Se basa en si misma

La terminologa de los rboles

Tambin puede ser definida en forma recursiva

Ejemplo: NIVEL de un rbol

nivel 1

SUB. DER.
Nivel 1

D
E

Identificar el caso recursivo y el caso mas bsico


A

Caso Bsico
Un rbol con un solo
nodo tiene nivel 1

S. izq.
Nivel 1

A
B

S. der.
Nivel 1

Nivel Del Arbol: 2

SUB.
IZQ.
SUB. IZQ.
SUB. IZQ.
Nivel
=
NivelSUB.
= 31 DER..
+
Nivel
=
1
Max(0,2) +
Max(0,Sub.Izq)
Nivel = 1
Max(0,Sub.Izq.)
Max(0,1)
NIVEL
:MAX(S.IZQ,
1 + MAX(3,
1)
NIVEL
: 1 +NIVEL
:4
S.DER)

Caso Recursivo
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


Todas sus hojas esta en el nivel h
Los nodos de altura menor a h tienen siempre 2 hijos

Recursiva

Si T esta vaco,

Entonces T es un rbol binario lleno de altura 0

Si no esta vaco, y tiene h>0

Esta lleno si los subrboles de la raz, son ambos rboles


binarios llenos de altura h-1

ARBOLES BINARIOS
COMPLETOS

Un arbol de altura h esta completo si

Todos los nodos hasta el nivel h-2


tienen dos hijos cada uno y

En el nivel h-1, si un nodo tiene un hijo


derecho, todas las hojas de su subarbol
izquierdo estn a nivel h

Si un arbol esta lleno, tambien esta


completo

OTROS

Un rbol equilibrado es cuando

La diferencia de altura entre los subrboles de cualquier nodo es


mximo 1

Un rbol binario equilibrado totalmente

Los subrboles izquierdo y derecho de cada nodo tienen las


misma altura: es un rbol lleno

Un rbol completo es equilibrado

Un rbol lleno es totalmente equilibrado

RECORRIDOS DE UN A.B.

Recorrer es

Visitar todos los elementos de una estructura

Como recorrer un rbol

Hay tantos caminos, cual escoger?


Existe tres recorridos tpicos

Nombrados de acuerdo a la posicin de la raz


Preorden: raz - subarbol izq. - subarbol der.
Enorden : subarbol izq. - raz - subarbol der.
Postorden : subarbol izq. - subarbol der. -raz

1. Visitar raiz
2. Preorden al Subarbol Izq.
3. Preorden al Subarbol Der.

EJEMPLO PREORDEN
G
1

12

10

13

I
11

G-D-B-A-C-E
G-D-B-A-C
G-D-B-A
G-D-B
G-D
G
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

Cada nodo

typedef struct NodoAB{


Generico G;
NodoAB *izq, *der;
}NodoAB;

Tiene Contenido y

Dos enlaces: rbol hijo izquierdo, rbol hijo derecho

Un nodo hoja, es aquel cuyos dos enlaces apunta a null

Solo se necesita conocer el nodo raz

Un nodo en un rbol tiene mas punteros a null que un nodo de una lista

De un rbol solo se necesita conocer su raz

La raz, que es un nodo, puede definir al rbol o


typedef struct NodoAB *AB;

NODOAB: OPERACIONES

Elemento de un rbol que


Almacena informacin (contenido),
Conoce hijo izq. y derecho, ambos son nodos

Operaciones Bsicas

Crear un nuevo nodo hoja y eliminar hoja existente

NodoAB *NodoAB_CrearHoja(Generico G);


void NodoAB_Eliminar (NodoArbol **A);

Saber si el nodo es o no hoja

bool NodoAB_EsHoja(NodoArbol *p);

NODOAB: MAS
OPERACIONES

Consultas de los campos de un nodo

Generico NodoAB_ConsultaContenido(NodoAB *nodo);

NodoAB *NodoAB_Izq (NodoAB *nodo);

NodoAB *NodoAB_Der(NodoAB *nodo);

Cambiar los campos de un nodo

void NodoAB_SetContenido (NodoAB *nodo , Generico G);

void NodoAB_SetIzq(NodoAB *nodo, NodoAB *enlace);

void NodoAB_SetDer(NodoAB *nodo, NodoAB *enlace);

AB: CREAR NODO HOJA

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

Crear y Eliminar
AB_Vaciar(AB *A);
AB_Eliminar(AB *A);

Estado del Arbol

bool AB_EstaVacio(AB A);

Aadir y remover nodos


void AB_InsertarNodo(AB *A, NodoAB *nuevo)
NodoAB *AB_SacarNodoxContenido(AB *A, Generico G, Generico_fnComparar fn);
NodoAB * AB_SacarNodoxPos(AB *A, NodoAB *pos);

Busqueda por contenido

NodoArbol *AB_Buscar(AB A, Generico G, Generico_fnComparar fn );

Recorridos
void AB_PreOrden(AB A);
void AB_PosOrden(ABl A);
void AB_EnOrden(AB A);

AB: INSTANCIANDO Y CREANDO

Un Arbol Vaco, es aquel cuyo nodo raz apunta a NULL


void AB_Vaciar(AB *A){
*A = NULL;
}

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

Instanciarlo (crear variable)


Vaciar el rbol

AB A;
AB_Vaciar(&A);

Para aadirle una hoja al rbol, crear hoja:

A = NodoAB_CrearHoja(Generico_CrearEntero(1));

A
1

RECORRIDOS:
IMPLEMENTACION

Como ya revisamos, las operaciones de recorrido son recursivas


Ejemplo: EnOrden

Recorrer EnOrden al subarbol izquierdo


Visitar nodo raiz
Recorrer EnOrden al subarbol derecho

En todo algoritmo recursivo debemos buscar dos casos

Bsico, para terminar la recursividad


Recursivo, donde la funcin se llama a si misma

Caso Bsico
Si AB_EstaVacio(raiz)

Terminar de recorrer

Caso Recursivo
Si !AB_EstaVacio(raiz)
AB_EnOrden(raiz->izq);
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);
}
}
A

Arbol
ArbolVacio!,
Vacio!,Terminar
Terminar

Arbol Vacio!, Terminar

4
B

APLICACIN: EVALUACION
DE EXPRESIONES

Ya sabemos lo de las expresiones, cierto?

InFija, operador en medio

PreFija, operador antes de dos operandos

PosFija, operador luego de dos operandos

Para evaluar una expresion dada, podriamos

Pasarla a posfija y usar solo pilas

Pasarla a posfija y usar pilas y un arbol de expresion

ARBOL DE EXPRESION

Arboles que representan expresiones en memoria

Todos los operadores tienen dos operandos

La raiz puede contener el operador

Hijo izq: operando 1, Hijo derecho: operando 2

Ejemplo: (a+b)

(a+b)*c
*

+
a

+
a

c
b

EJERCICIO EN CLASE

Construya arboles de expresion para:

[X+(Y*Z)] * (A-B)

Deducir las expresiones de los siguientes A.B.


+
a

+
c

EVALUAR UNA EXPRESION


ARTIMETICA EN INFIJA

La expresion se transforma a la expresion posfija

Crear un arbol de expresion

Esto, ya sabemos como hacer

Para esto se va a usar una pila y un arbol de caracteres

Usando el arbol, evaluar la expresion

CREAR UN ARBOL DE
EXPRESION

Los operandos seran siempre nodos hoja del arbol

Al revisar un operando, creo una nueva hoja y la recuerdo

Los operadores seran nodos padre

Al revisar un operador, recuerdo las dos ultimas hojas creadas y uno todo
No debo olvidar el nuevo arbolito que he creado

A*B-C*D+H

AB*CD*-H+

+
-

D
H
B

C
*
A

D
A

A
*

*
B

EVALUACION DE LA EXP.
POSTFIJA

Lo ideal es recuperar los dos operandos, el operador, y ejecutar la opcion


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

+
-

1. Res1 = Evaluo subarbol izquierdo


2. Res2 = Evaluo subarbol derecho

*
A

Si no

A*
(A
y*BB) y- (C*D)
CyD+
(C*D)
y HH

3. Recupero la info de la raiz y efectuo la


operacin alli indicada, entre Res1 y Res2

ARBOL BINARIO DE
BUSQUEDA

<>
55

30

Los elementos en un arbol

Hasta ahora no han guardado un orden

No sirven para buscar elementos

75
41

85

Los arboles de busqueda

Permiten ejecutar en ellos busqueda binaria

Dado un nodo:

Todos los nodos del sub. Izq. Tienen una clave menor que
la clave de la raiz
Todos los nodos del sub. Der. Tienen una clave mayor que
la clave de la raiz

<>
6
4

9
5

TDA ABB: DEFINICION

Valores:

Conjunto de elementos
Dado un nodo p,

<abb>::= NULL | <abb_nodo>


<abb_nodo>::=<clave>+<contenido>+<izq>+<der>
<izq>::=<abb>
<der>::=<abb>
<clave>::<<dato>>|{<<dato>>}
<contenido>::<<dato>>|{<<dato>>}

Los nodos del arbol izquierdo almacenan valores mayores al de p


Los nodos del arbol derecho almacenan valores menores al de p

Operaciones

Son las mismas operaciones que para un AB


Pero en este caso ya tenemos reglas suficientes que nos indican como:
Insertar
Sacar y
Buscar

typedef struct ABB_Nodo{


Generico clave, G;
ABB_Nodo *izq, *der;
}ABB_Nodo;

CREAR CON CLAVE

Como el nodo ahora tiene un campo clave

Cambian un poco las operaciones del nodo

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

Un arbol de busqueda debe mantener

A la derecha mayor a raiz


A la izq. Menor a raiz

Ejemplo:

Construya arbol con los siguientes elementos:

8, 3, 1, 20, 10, 5, 4
8

20

5
4

10

EJERCICIO EN CLASE

Construya el arbol para almacenar:

12, 8, 7, 16, 11

BUSQUEDA DE UN NODO

Dada una clave, devolver el nodo que la contiene


Se comienza en la raiz

Si el arbol esta vacio

Si clave buscada es igual a la clave del nodo evaluado

No se encontro

Buscar(raiz,25)
Buscar(raiz,5)

BINGO, LO ENCONTRE

Si no
Si la clave buscada es mayor a la del nodo evaluado
Buscar en el subarbol derecho
Si no
1
Buscar en el subarbol izquierdo

20
5
4

10
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

Muy parecido a la busqueda

Debo insertar en la posicion correcta

Insertar(raiz,15)
15>8der

El arbol debe mantener sus propiedades

Pasos:

Crear una nueva hoja

Buscar en el arbol donde ponerla

Enlazar el nuevo nodo al arbol

15<20izq

8
15>10
der

3
1

10

20
Insertar
aqui

4
15

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{

else if(f(nuevo->clave, (*A)->clave) <0)


ABB_Insertar((*A)->izq,nuevo,f);
else
return FALSE;
//Si esta vacio, alli insertar
*A = nuevo;

}
return TRUE;

ELIMINACION DE UN
NODO

Es mas compleja que la insercion


Al sacar un nodo del arbol

Eliminar(raiz,34)

El arbol debe mantener sus propiedades


El arbol debe reajustarse

Pasos:

Buscar el nodo p que se va a eliminar

Si el nodo a eliminar tiene menos de dos hijos


Subir el nodo hijo a la pos. del nodo eliminado

Si no

34
28
18

Ubicar el nodo q con la mayor de las claves menores


Reemplazar contenido de p con el del nodo q
Eliminar el nodo q que se encontro el el primer paso

90

25
20

100
28
nmayor

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;
}

Potrebbero piacerti anche