Download Ing. En Sistemas Computacionales Estructura de Datos Unidad V

Document related concepts

Árbol binario wikipedia , lookup

Recorrido de árboles wikipedia , lookup

Árbol binario de búsqueda wikipedia , lookup

Rotación de árboles wikipedia , lookup

Árbol (informática) wikipedia , lookup

Transcript
Ing. En Sistemas Computacionales
Estructura de Datos
Unidad V Estructuras no lineales
estáticas y dinámicas.
(Árboles y grafos)
Ing. Néstor Alejandro Carrillo López
Arboles
Un árbol es un conjunto finito de nodos:
1. Si la colección es vacía, se dice que el árbol es
vacio
2. En caso contrario, un árbol A consiste de un
nodo especial llamado raíz y n (sub)arboles no
vacios T1,T2,…,Tn. La raíz de A se conecta con la
raíz de cada Ti por un arco dirigido.
Relaciones entre nodos
Todo nodo nj, exceptuando el raíz, esta
conectado exclusivamente a otro nodo nk
donde:
• nj es el padre de nk (Ej., B es el padre de E)
• nk es uno de los hijos de nj (Ej., E es un hijo de B)
• Nodos con el mismo padre son “hermanos” (Ej., B , C y D)
• Nodos sin hijos son llamados “hojas” (Ej., G)
Árboles binarios
• Un árbol binario es un
árbol en el cual cada
nodo puede tener como
máximo dos hijos
• Un árbol binario se
define como:
– un árbol vacio, o
– un nodo raíz con un
subárbol izquierdo y un
subárbol derecho
Representación en Memoria
Hay dos formas tradicionales de representar un
árbol binario en memoria:
• Por medio de datos tipo punteros también
conocidos como variables dinámicas o listas.
• Por medio de arreglos(estáticas).
Sin embargo, la más utilizada es la primera, puesto
que es la más natural para tratar este tipo de
estructuras.
Representación en Memoria
• Los nodos del árbol binario serán
representados como registros que contendrán
como mínimo tres campos. En un campo se
almacenará la información del nodo. Los dos
restantes se utilizarán para apuntar al subárbol
izquierdo y derecho del subárbol en cuestión.
• Cada nodo se representa gráficamente de la
siguiente manera:
Declaración de árbol binario
• Se definirá el árbol con un dato de tipo objecto (puede ser cualquier
otra tipo de datos) y dos hijos: izquierdo (izq) y derecho (der). Para
representar los enlaces con los hijos se utilizan punteros. El árbol vacío
se representará con un puntero nulo.
• La clase nodo binario puede declarar de la siguiente manera:
Class NodoB{
Object dato;
NodoB izq;
NodoB der;
NodoB (){ this (null);}
NodoB ( Object o ) { this(o,null,null);}
NodoB(Object o, NodoB i, NodoB d) {dato=0; izq=i; der=d;}
}
Declaración de árbol binario
•
Se definirá el árbol con un dato de tipo objecto (puede ser cualquier otra tipo de datos)
y dos hijos: izquierdo (izq) y derecho (der). Para representar los enlaces con los hijos se
utilizan punteros. El árbol vacío se representará con un puntero nulo.
•
La clase nodo binario puede declarar de la siguiente manera:
public class NodoBinario {
//atributos
Object dato;
NodoBinario izquierdo;
NodoBinario derecho;
//constructores
public NodoBinario()
{
this(null); }
public NodoBinario(Object elDato)
{ this( elDato, null, null); }
public NodoBinario(Object elDato, NodoBinario menor, NodoBinario mayor)
{
dato=elDato;
izquierdo=menor;
derecho=mayor; }
Operaciones básicas en arboles
•
•
•
•
•
Crear un árbol vacio
Verificar si el árbol esta vacio
Insertar un nodo
Eliminar un nodo
Recorrer un árbol
Recorridos de arboles
• Procedimientos que visitan todos los nodos de un
árbol efectuando una acción sobre cada uno.
• Existen dos formas posibles de recorrer un árbol no
vacio
Amplitud: el proceso se realiza horizontalmente
desde la raíz a todos sus hijos, luego a los hijos de
sus hijos y así sucesivamente
Profundidad: se sigue un camino desde la raíz a
través de un hijo antes de proseguir al siguiente
hijo
Ejemplo de recorrido en amplitud
Recorridos en profundidad
• Existen tres formas posibles de recorrer en
profundidad un árbol no vacio, según cuando
la raíz sea visitada
Recorrido
Características
Pre orden
se visita la raíz;
se recorre el subárbol izquierdo;
se recorre el subárbol derecho;
inorden
se recorre el subárbol izquierdo;
se visita la raíz;
se recorre el subárbol derecho;
Post-orden
se recorre el subárbol izquierdo;
se recorre el subárbol derecho;
se visita la raíz;
Recorridos en profundidad
• Pre orden
se visita la raíz;
se recorre el subárbol izquierdo;
se recorre el subárbol derecho;
Recorridos en profundidad
• Recorrido inorden
se recorre el subárbol izquierdo;
se visita la raíz;
se recorre el subárbol derecho;
Recorridos en profundidad
• Post-orden
se recorre el subárbol izquierdo;
se recorre el subárbol derecho;
se visita la raíz;
Carga (Nodo)
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
1. leer información (INFO)
2. Hacer NODO^.INFO <- INFO
3. Escribir “Existe nodo por la izquierda?”
4. Leer respuesta
5. Si respuesta es afirmativa
entonces
CREA (OTRO) {Crear un nuevo nodo}
Hacer NODO^.IZQ<-OTRO
Regresar a CARGA con NODO^.IZQ
{Llamada recursiva}
si no
Hacer NODO^.IZQ<-Null
6. {Fin del condicional del paso 5}
7. Escribir “Existe nodo por derecha?”
8. Leer respuesta
9. Si respuesta es afirmativa
entonces
CREA (OTRO) {Crea un nuevo nodo}
Hacer NODO^.DER <-OTRO
Regresar a CARGAR con NODO^.DER
{Llamada recursiva}
si no
Hacer NODO^.DER<- Null
10. {Fin de condicional del paso 9}
Algoritmo de preorden
PREORDEN(NODO)
{El algoritmo realiza el recorrido preorden en un árbol binario.
NODO es un dato de tipo puntero }
{INFO, IZQ Y DER son campos del registro nodo. INFO es una
variable de tipo carácter. IZQ y DER son variables de tipo
puntero}
1. Si NODO <> Null entonces
visitar el NODO {Escribir NODO^.INFO}
Regresar a PREORDEN con NODO^.IZQ
{Llamada recursiva a PREORDEN con la rama izquierda del
nodo en cuestión}
Regresar a PREORDEN con NODO^.DER
{Llamada recursiva a PREORDEN con la rama derecha del
nodo en cuestión}
2. {Fin de condicional del paso 1}
INORDEN (NODO)
{El algoritmo realiza el recorrido inorden en un árbol binario.
NODO es un registro de tipo puntero}
{INFO, IZQ y DER son campos del registro nodo. INFO es una
variable de tipo carácter. IZQ y DER son variables de tipo
puntero}
1. Si NODO <> Null entonces
Regresar a INORDEN con NODO^.IZQ
{Llamada recursiva a INORDEN con la rama izquierda del nodo
en cuestion}
Visitar el NODO {Escribir NODO^.INFO}
Regresar a INORDEN con NODO^.DER
{Llamada recursiva a INORDEN con la rama derecha del nodo
en cuestión}
2. {Fin de condicional del paso 1}
POSTORDEN(NODO)
{El algoritmo realiza el recorrido postorden en un árbol binario. NODO es
un dato de tipo puntero}
{INFO, IZQ y DER son campos del registro nodo. INFO es una variable de
tipo carácter IZQ y DER son variables de tipo puntero}
1. Si NODO<>Null entonces
Regresa POSTORDEN con NODO^.IZQ
{Llamada recursiva a POSTORDEN con la rama izquierda del nodo en
cuestión}
Regresar a POSTORDEN con NODO^.DER
{Llamada recursiva a POSTORDEN con la rama derecha del nodo en
cuestion}
Visitar el NODO {Escribir NODO^.INFO}
2. {Fin de condicional del paso 1}
Grafos
• Un grafo G es un par (V,E), tal que:
V: conjunto de nodos
E: conjunto de arcos conectando a los nodos en V
Un arco e = (u,v) es un par de nodos
Grafos dirigidos y no dirigidos
• Dirigido (o Digrafo)
Cada linea tiene una direcciona su sucesor
Note que <vi, vj> ≠ <vj, vi>
• No dirigido
Las lineas no tienen direccion
Note <vi, vj> = <vj, vi>。
Operaciones en grafos
• Considere un grafo G y dos nodos x y y
-añade(G, x,y): añade en G un arco de x a y, si no existe
- borra(G, x,y): suprime un arco de x a y, si existe
- adyacente(G, x,y): verifica si hay un arco de x a y en G
- vecinos(G, x): lista todos los nodos y tal que hay un
arco entre x y y
Operaciones en grafos
• En los grafos que tienen valores asociados a sus
arcos, también se tienen:
- asigna_valor(G, x,y,v): asigna el valor asociado
al arco (x,y) a v.
-obtener_valor(G, x,y): regresa el valor asociado
al arco (x,y).