Page 1

UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

CLAVE DE LA ASIGNATURA

CUATRIMESTRE

PARA-ES

8

NÚMERO DE PRÁCTICA 2

NOMBRE DE LA ASIGNATURA PROGRAMACIÓN AVANZADA

NOMBRE

DURACIÓN (HORAS)

RECORRIDOS SOBRE GRAFOS

4

INTRODUCCIÓN: Las funciones de recorrido de grafos son extensiones de los recorridos utilizados en las estructuras tipo árbol. El objetivo es visitar todos los nodos del grafo exactamente una vez. Cuando se visita, es con la intención de realizar algún cálculo sobre él, ya sea simplemente imprimir su información u obtener algún resultado a partir de los valores de los nodos visitados. Si el objetivo de un recorrido es simplemente pasar por todos los nodos del grafo, basta con hacer una pasada por el conjunto de nodos. Al recorrer se sigue una topología, es decir, lo recorremos siguiendo los caminos definidos en el por los arcos. Existen dos estrategias de recorrido diferentes:  Primero en profundidad.  Primero en amplitud o anchura.

OBJETIVO: Implementar los recorridos de un grafo: primero en profundidad y primero en amplitud en la solución de problemas computables.

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 1


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

TEORÍA: El algoritmo primero en profundidad (depth firts), tiene el siguiente procedimiento: 1. Inicializar todos los nodos del grafo en el estado: en espera. 2. Para cada nodo del grafo: 2.1. Si el estado es en espera entonces 2.1.1. Insertar el nodo en pila (cambiar su estado a listo). 2.1.2. Mientras la pila de nodos listos no esté vacía. Sacar un nodo de la pila y procesarlo. Cambiar su estado ha procesado. Meter en la pila todos los nodos vecinos del nodo recién sacado cuyo estado sea en espera o listo. Nota: si el nodo ya existe en la pila (con estado de listo) se deja sólo el que llegó al último (el más reciente). El pseudocódigo sería el siguiente: Algoritmo PrimeroEnProfundidad(G: Grafo; n: Elemento); Variables p: Pila l, m: Elemento Inicio P:=Crear(); Marcar(n); Apilar(p, n); MIENTRAS NOT Vacía(p) HACER m := Cima(p) Desapilar(c) Marcar(m) Procesar(m) PARA TODO nodo l sin marcar adyacente a m HACER Marcar(l) Apilar(c, l) FIN PARA FIN MIENTRAS Fin PrimeroEnProfundidad

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 2


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

Ejemplo Se tiene el grafo no dirigido mostrado en la figura siguiente A

B

D

E

C F

G

Supongamos que el elemento inicial es el nodo A. se guarda en la pila, como la pila no está vacía, precisamente contiene el nodo A, se saca el primer elemento. Al no estar marcado, se marca y se procesa. Se puede suponer que en este caso el procesamiento consiste en escribir su valor en pantalla. Los dos elementos adyacentes son B y D, ambos están sin marcar y se incluyen en la pila.

La pila no está vacía por lo que se saca el elemento de la cima, D, que no está marcado. Se marca y se escribe por pantalla. Los nodos adyacentes a D son C, F y G, ninguno de los cuales está marcado. Por tanto, se apilan los tres. Se saca el elemento de la cima de la pila, G y se escribe por pantalla. El único nodo adyacente a G sin marcar es E, porque d ya está marcado, por lo que sólo se apila e, que pasa a ser la nueva cima. Se saca E de la pila y se procesa. No hay ningún sucesor de E que no haya sido marcado, por tanto no se apila ningún elemento. En este momento, la cima de la pila es F. Se saca y se procesa. Los tres nodos adyacentes a F son D, E, y G que todos están marcados, por lo que no se apilan. Se saca la cima de la pila, el nodo B, que se procesa. Sus nodos adyacentes, A y E, no se apilan al estar ya marcados. Se vuelve a sacar la cima, que esta vez es C, que está aún sin marcar. Pon tanto, se marca y se procesa. Como todos sus nodos adyacentes están marcados, no se apila ninguno. Y finalmente se saca el único elemento ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 3


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

que queda en la pila. Se procesa B y se acaba el bucle, por estar vacía la pila. El resultado por pantalla sería entonces: A, D, G, E, F, C, B.

El contenido de la pila en el recorrido primero en profundidad es:

El algoritmo primero en anchura (breadth firts) se realiza bajo el siguiente procedimiento: 1. Inicializar todos los nodos del grafo en el estado: en espera. 2. Para cada nodo del grafo: 2.1. Si el estado es en espera entonces 2.1.1. Insertar el nodo en una fila (cambiar su estado a listo). 2.1.2. Mientras la fila de nodos listos no esté vacía. Sacar un nodo de la fila y procesarlo. Cambiar su estado a procesado. Meter en la fila todos los nodos vecinos del nodo recién sacado cuyo estado sea en espera. Cambiar el estado de esto nodos a listos.

El recorrido en amplitud es similar al recorrido por niveles de un árbol, si consideramos como un nivel el conjunto de los nodos adyacentes. En este recorrido, tras visitar un nodo, se visitan todos sus nodos adyacentes. Una vez visitados todos los nodos de este primer nivel, se repite el proceso visitando todos los nodos adyacentes del primer vecino de nivel recién recorrido y repitiéndolo para todos los nodos hasta que no quede ninguno por visitar.

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 4


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

En el recorrido en profundidad usábamos una pila como estructura auxiliar para recorrer el grafo. Aunque en el recorrido en amplitud no hacemos vuelta atrás también necesitamos almacenar temporalmente los nodos. Para guardarlos en el orden adecuado, usaremos una estructura tipo cola en vez de una pila. El Pseudocódigo sería el siguiente:

Algoritmo PrimeroEnAmplitud(G: Grafo; n: Elemento); Variables c: Cola l, m: NODO Inicio C := Crear() Marcar(n) Insertar(c, n) MIENTRAS NOT Vacía(c) HACER m := Frente(c) Extraer(c) PARA TODO nodo l sin marcar adyacente a m HACER Marcar(l) Insertar(c, l) FIN PARA FIN MIENTRAS Fin PrimeroEnAmplitud

Si hacemos PrimeroEnAmplitud(G, a), siendo G el nodo del ejemplo anterior tendremos la siguiente secuencia. Se inserta a en la cola. Como la cola no está vacía, se extrae el primer elemento, que es A, por ser el único. Se inserta los nodos adyacentes a A sin marcar: B y D. Como la cola no está vacía, se saca el primer elemento de la cola, B, y se inserta los nodos adyacentes no visitados. Sólo se inserta E. Ahora el frente de la cola es D. Se saca y se guarda sus sucesores: C, F y G. El siguiente elemento que sale de la cola ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 5


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

es E, al que no le queda ningún vecino sin marcar. Igual pasa con C, F y finalmente G. Llegados a este punto, la cola se ha quedado vacía y se acaba el algoritmo. El recorrido ha sido: A, B, C, D, E, F, G.

DESARROLLO:

1. Implemente el código de generación de los nodos del grafo

import java.util.ArrayList; public class Nodo { private Object dato; private ArrayList<Nodo> nodo; public boolean visitado = false; public Nodo(){ this(new Object()); } public Nodo(Object dato){ this.dato = dato; nodo = new ArrayList<Nodo>(); } public void setDato(Object dato){ this.dato = dato; } public Object getDato(){ return this.dato; } public void setNodo(Nodo nodo){ this.nodo.add(nodo); } public ArrayList<Nodo> getHijos(){ return nodo; } }

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 6


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

2. Implemente un grafo por medio de listas de adyacencias, para ello verifique el funcionamiento del siguiente código con el grafo ejemplo de la sección de teoría: import java.util.ArrayList; public class Grafo { private ArrayList<Nodo> listaNodo; public Grafo(){ listaNodo = new ArrayList<Nodo>(); } public void adjuntarNodo(Nodo nodo){ listaNodo.add(nodo); } public void crearEnlaces(Object nombreNodoPadre,Object nombreNodoHijo){ Nodo padre = buscarNodo(nombreNodoPadre); Nodo hijo = buscarNodo(nombreNodoHijo); if(padre != null && hijo != null){ padre.setNodo(hijo); } } public Nodo buscarNodo(Object nombreNodo) { Nodo temp = null; for(int i = 0;i < listaNodo.size(); i++) { if(((String)nombreNodo).equals((String)listaNodo.get(i).getDato())) { return listaNodo.get(i); } } return temp; } }

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 7


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

3. A continuación se presenta el procedimiento de implementación de pila y cola para los recorridos por anchura y amplitud del grafo import java.util.ArrayList; public class Cola extends ArrayList{ public Cola(){ super(); } public void addNodo(Nodo nodo){ if(!this.contains(nodo) && nodo.visitado != true){ add(nodo); System.out.println(); mostrarContenido(); } } public Nodo getNodo(){ Nodo nodoTemp = null; if(!this.isEmpty() && this != null){ nodoTemp = (Nodo)this.get(0); this.remove(0); } return nodoTemp; } public void mostrarContenido(){ System.out.print("["); for(int i = 0;i < this.size();i++){ System.out.print(((Nodo)this.get(i)).getDato()); } System.out.print("]"); } }

import java.util.ArrayList; public class Pila extends ArrayList{ public Pila() { super(); } public void addNodo(Nodo nodo){ if(!this.contains(nodo) && nodo.visitado != true){ add(nodo); System.out.println(); mostrarContenido(); } }

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 8


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

public Nodo getNodo(){ Nodo nodoTemp = null; if(!this.isEmpty() && this != null){ nodoTemp = (Nodo)this.get(this.size() - 1); this.remove(this.size() - 1); } //mostrarContenido(); return nodoTemp; } public void mostrarContenido(){ System.out.print("["); for(int i = 0;i < this.size();i++){ System.out.print(((Nodo)this.get(i)).getDato()); } System.out.print("]"); } }

4. Implemente los recorridos para el grafo. public class Recorrido{ private Pila pila; private Cola cola; public Recorrido(){ pila = new Pila(); cola = new Cola(); } private void llenarPilaNodosAdyacentes(Nodo nodo){ for(int i = 0; i < nodo.getHijos().size();i++){ if(!nodo.getHijos().contains(nodo)){ pila.addNodo(nodo.getHijos().get(i)); } } } private void llenarColaNodosAdyacentes(Nodo nodo){ for(int i = 0; i < nodo.getHijos().size();i++){ if(!nodo.getHijos().contains(nodo)){ cola.addNodo(nodo.getHijos().get(i)); } } }

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 9


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

public void recorrerProfundidadIterativo(Grafo grafo,Nodo nodoInicio){ if(grafo != null && nodoInicio != null){ pila.addNodo(nodoInicio); while(pila.size() > 0){ Nodo nodoVisitado = pila.getNodo(); if(nodoVisitado.visitado == false){ nodoVisitado.visitado = true; System.out.print(nodoVisitado.getDato()+","); llenarPilaNodosAdyacentes(nodoVisitado); } } } } public void recorrerAmplitud(Grafo grafo,Nodo nodoInicio){ if(grafo != null && nodoInicio != null){ cola.addNodo(nodoInicio); while(cola.size() > 0){ Nodo nodoVisitado = cola.getNodo(); if(nodoVisitado.visitado == false){ nodoVisitado.visitado = true; System.out.print(nodoVisitado.getDato()+","); llenarColaNodosAdyacentes(nodoVisitado); } } } } }

5. Complete el programa y verifique los recorridos. public class Main{ static Grafo grafo; public static void llenandoGrafo(){ grafo = new Grafo(); grafo.adjuntarNodo(new Nodo("A")); grafo.adjuntarNodo(new Nodo("B")); grafo.adjuntarNodo(new Nodo("C")); grafo.adjuntarNodo(new Nodo("D")); grafo.adjuntarNodo(new Nodo("F"));

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 10


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

grafo.crearEnlaces("A","B");// de A hacia B grafo.crearEnlaces("B","A");// de B hacia A /* * Lo anterior se realiza por ser un grafo no dirigido... * */ grafo.crearEnlaces("A","C"); grafo.crearEnlaces("C","A"); grafo.crearEnlaces("A","F"); grafo.crearEnlaces("F","A"); // //

grafo.crearEnlaces("B","A");//Esta enlace ya existe grafo.crearEnlaces("A","B");//Esta enlace ya existe

grafo.crearEnlaces("B","F"); grafo.crearEnlaces("F","B"); // //

grafo.crearEnlaces("C","A");//Esta enlace ya existe grafo.crearEnlaces("A","C");//Esta enlace ya existe

grafo.crearEnlaces("C","D"); grafo.crearEnlaces("D","C"); // //

grafo.crearEnlaces("D","C");//Esta enlace ya existe grafo.crearEnlaces("C","D");//Esta enlace ya existe

// //

grafo.crearEnlaces("F","A");//Esta enlace ya existe grafo.crearEnlaces("A","F");//Esta enlace ya existe

// //

grafo.crearEnlaces("F","B");//Esta enlace ya existe grafo.crearEnlaces("B","F");//Esta enlace ya existe

} public static void main(String []args){ llenandoGrafo(); Recorrido recorrido = new Recorrido(); System.out.println("----------------------------------------------"); System.out.println("Recorrido en profundidad"); recorrido.recorrerProfundidadIterativo(grafo,grafo.buscarNodo("A")); System.out.println(); llenandoGrafo(); ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 11


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

System.out.println("----------------------------------------------"); System.out.println("Recorrido en Amplitud"); recorrido.recorrerAmplitud(grafo,grafo.buscarNodo("A")); System.out.println(); System.out.println("----------------------------------------------"); } }

6. Modifique el código para 6.1. Genere la salida al terminar la ejecución de cada recorrido sin los valores intermedios. 6.2. Construir el grafo a partir de los valores proporcionados por el usuario.

ACTIVIDADES COMPLEMENTARIAS: A. Se podría encontrar un camino en el grafo a partir de los recorridos por profundidad y por anchura. Dichos algoritmos se basan en llevar un registro del padre de cada nodo en el recorrido, eso se puede conseguir agregando una línea que guarde un arreglo de padres cuando se meten los vértices no visitados a la pila o cola de adyacentes. Como se sabe que cada nodo que se mete a la pila proviene del nodo_actual en el recorrido, basta con añadir una línea como padre[nodo_actual] = *aux; dentro del ciclo que añade los nodos no visitados a la pila o cola. Modifique el código para implementar esto.

B. Realizar la siguiente aplicación en lenguaje Java: Una refinería desea enviar la máxima cantidad posible de petróleo (por hora) a través de un sistema de tuberías desde el nodo So al nodo Si de la Figura. El petróleo debe pasar a través de una o varias estaciones (1, 2 o 3). Los arcos representan tuberías de distintos diámetros. El número máximo de barriles de petróleo (millones de barriles por hora) que pueden ser bombeados a través de cada arco se indican en la Figura. Formule una aplicación, que determine el numeró máximo de barriles que pueden ser enviados a través del sistema de tuberías, así como cual es la ruta más óptima.

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 12


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

Como So es un nodo fuente, del que solo puede salir flujo. Como S i es un destino, solo puede recibir flujo. Para formular el modelo emplearemos las variables: Xij = cantidad de barriles enviadas a través del arco (i; j) El flujo en cada arco debe satisfacer la restricción: 0 < =flujo por el arco <= capacidad del arco En cada nodo se debe satisfacer que: Flujo entrante al nodo i = flujo saliente del nodo i Asumiendo que es X0 el flujo a través de la red, la función objetivo sería entonces maximizar X0.

CONCLUSIONES:

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 13


UNIVERSIDAD POLITÉCNICA DEL VALLE DE MÉXICO INGENIERÍA EN INFORMÁTICA PRACTICA 2: RECORRIDOS SOBRE GRAFOS

BIBLIOGRAFÍA: 1. Caíro, O., & Guardatii, S. (2006). Estructura de datos. Mc Graw Hill. 2. Ceballos, F. J. (2011). Java 2: Curso de Programación. México: Alfaomega. 3. Franch, X. (2002). Estructura de Datos: Especificación, Diseño e Implementación. Alfaomega. 4. Loomis, M. E. (1990). Estructura de datos y Organización de archivos. Prentice Hall.

ELABORO: M. en D. Bibiana Pérez Castillo Pérez

REVISO: Página | 14

Unidad i practica 2a1 programación avanzada upvm  

bla bla bla

Advertisement