Documentos de Académico
Documentos de Profesional
Documentos de Cultura
representaciones.
Recorridos, caminos
mínimos e implementación
en Java
Taller de
Algoritmos
y Estructura
de Datos II
1
Introducción
El objetivo de esta unidad es realizar una introducción a una estructura de
datos muy utilizada como son los grafos. En esta unidad se presentarán los
conceptos esenciales para comprender su funcionamiento, lo cual nos
permitirá realizar nuestra propia implementación en Java. Además,
analizaremos distintos problemas tipos, las distintas representaciones y los
algoritmos para el recorrido y solución de problemas.
Conceptos básicos
Un grafo es un conjunto de vértices o nodos unidos por aristas o arcos.
Típicamente, un grafo se representa gráficamente como un conjunto de
puntos (vértices o nodos) unidos por líneas (aristas) como se puede ver en
la Figura 1 y 2.
Los grafos también pueden ser dirigidos (o dígrafos), y en ese caso (v,w) se
trata un par ordenado.
Observe que en este caso es válido ir de 12, pero el camino directo de 21
no existe.
Adyacencia
Decimos que un vértice w es adyacente a un vértice v si existe una arista
(v,w) en E. En el caso de grafos no dirigidos, si w es adyacente a v, entonces
v es adyacente a w. En el caso de dígrafos, esto no se cumple, a no ser que
tanto (v,w) y (w.v) sean aristas del grafo.
Algunas veces, las aristas tienen un peso o costo asociado (v,w,p), v,w ε
V, p ε R.
Grafos conexos
Un grafo es conexo si cada par de vértices está conectado por un
camino, es decir, si para cualquier par de vértices (1, 2), existe al menos
un camino posible desde 1 hacia 2.
En la siguiente figura se muestra un ejemplo de grafos conexos y no
conexos.
Caminos
Un camino es una secuencia de vértices w1,..,wN donde (wi,wi+1) ε E,
para 1≤ i < N.
Representación de
Grafos
Uno de los primeros problemas a resolver es cómo se representan
internamente los grafos.
Por otro lado, cuando nos encontramos ante un grafo disperso, resulta más
eficiente utilizar una estructura de datos de tipo lista de adyacencia.
Una lista de adyacencia consiste de una lista de los vértices del grafo y para
cada vértice de una lista de sus vértices vecinos.
Lo que se hace es definir una lista enlazada para cada nodo, que contendrá
los nodos a los cuales es posible acceder. Es decir, un vértice i tendrá una
lista enlazada asociada en la que aparecerá un elemento con una referencia al
vértice j si i y j tienen una arista que los une. Obviamente, si el grafo es no
dirigido, en la lista enlazada de j aparecerá la correspondiente referencia al
vértice i. En este caso el espacio ocupado es n*m, muy distinto del necesario
en la matriz de adyacencia, que era de n2. La representación por listas de
adyacencia, por tanto, será más adecuada para grafos dispersos.
1
http://docencia.udea.edu.co/regionalizacion/teoriaderedes/representacionordenadoru1.html
Figura 9: Representación con listas de adyacencia
Problemas tipo
Esta estructura de datos es muy utilizada dado que nos sirve para
representar numerosas situaciones y problemas conocidos:
Ciudades y rutas: cada nodo representa una ciudad y cada arista una
ruta que une dichas ciudades. ¿Cuál es el camino más corto? ¿Hay
un camino que partiendo de una ciudad visite todas las ciudades
una sola vez volviendo a la ciudad de partida?
Figura 10: Ciudades y rutas
Figura 13 – Ejemplo DFS - Fuente: Libro “Data Structures and Algorithms in Java” – Robert
Lafore, pág. 625.
Búsqueda en anchura
(BFS), Búsqueda en
Profundidad (DFS), Floyd,
Dijstra.
En un grafo todos los caminos tienen un peso asociado, el cual está indicado
por las suma de los pesos de las aristas que forman el camino. Existen
numerosas situaciones problemáticas en donde queremos encontrar el
camino que minimice estos valores.
Algoritmo de Dijkstra
“El algoritmo de dijkstra determina la ruta más corta desde un nodo origen
hacia los demás nodos para ello es requerido como entrada un grafo cuyas
aristas posean pesos. Algunas consideraciones”:
“Si los pesos de mis aristas son de valor 1, entonces bastará con usar
el algoritmo BFS”.
“Si los pesos de mis aristas son negativos no puedo usar el algoritmo
de dijsktra, para pesos negativos tenemos otro algoritmo llamado
Algoritmo de Bellmand-Ford”.
“Dijkstra es muy similar a BFS, si recordamos BFS usaba una Cola para el
recorrido para el caso de Dijkstra usaremos una Cola de Prioridad o Heap,
este Heap debe tener la propiedad de Min-Heap es decir cada vez que
extraiga un elemento del Heap me debe devolver el de menor valor, en
nuestro caso dicho valor será el peso acumulado en los nodos.”
(Jhosimar George Arias Figueroa, 2012,
http://jariasf.wordpress.com/2012/03/19/camino-mas-corto-algoritmo-
de-dijkstra/)
Figura 15: Grafo dirigido con pesos. Fuente: Libro “Data Structures and Algorithms in
Java” – SAMS, pág. 708.
Este algoritmo compara todos los posibles caminos entre cada par de
vértices. Se va a utilizar una matriz Ak[i][j], que contiene el camino más
corto que pasa por los primeros k primeros vértices.
Inicialmente Ak[i][j] = matriz de adyacencia i j. Si no hay arista de i a j
el costo será (infinito) y los elementos diagonales se ponen a 0.
En la iteración k (nodo k como pivote) se calcula, para cada camino de v a
Ak[i][j] = min (Ak-1[i][j] , Ak-1[i][k] + Ak-1[k][j] ), i j.
Básicamente la expresión anterior nos dice: “si para ir desde el vértice “i” al
“j” mejoramos pasando por el vértice “k”, éste se añade al camino. Además,
para reconstruir el camino se hace uso de una matriz de trayectorias, donde
en cada iteración, si se mejora el camino desde el vértice “i” al vértice “j”
pasado por “k”, éste se anota en la matriz de trayectorias.
Figura 16: Ejemplos Floyd. Fuente: Libro “Data Structures and Algorithms in Java” –
SAMS, pág. 708.
4. Ak[3][0] = min ( , 50 ), i j.
5. Ak[3][0] = 50
5. Ak[1][0] = 60
Este ejemplo nos muestra que por la forma de recorrer el grafo, este
algoritmo nos resuelve la problemática caminos mínimos en grafos sin
peso.
Implementación de la estructura de
Grafos
Clases
Para la implementación de esta estructura de datos crearemos:
Clase Vértice: Esta clase representa los vértices o nodos del grafo.
Clase Arista: Esta clase representa las aristas o arcos del grafo.
Para el caso de las aristas, creamos una clase llamada Arista en la que
guardamos el Vértice destino a donde esta arista se dirige y el costo que
insume ir desde el origen al destino. En el caso de grafos sin peso este valor
se va a establecer en 1.
Pasos de ejecución:
1) El primer paso del algoritmo consiste en inicializar todos los vértices del
grafo. Este paso consiste en inicializar la variable distancia de cada uno
de los vértices en Infinito. (Ver llamada al método clearAll() de la Figura
22).
Implementación DFS
Para efectuar un recorrido en profundidad de un grafo, se selecciona
cualquier nodo como punto de partida (por lo general el primer nodo del
grafo) y se marcan todos los nodos del grafo como “no visitados”. El nodo
inicial se marca como “visitado” y si hay un nodo adyacente a este que no
haya sido “visitado”, se toma este nodo como nuevo punto de partida del
recorrido. El recorrido culmina cuando todos los nodos hayan sido visitados.
Pasos de ejecución:
1 2 3 4 5 6 7 8 9 10 11 12
7 8 2 6 2 3 8 9 5 1 4 8
10 4 11 10 12 12 5 12
11
V1 V7 V1-v7 V1,v7
V1,v7,v8,v9,v5,v2 * V1,v7,v8,v9,v5,v2
V1,v7,v8,v9,v5 * V1,v7,v8,v9,v5,v2
V1,v7,v8,v9,v12 * V1,v7,v8,v9,v5,v2,v12
V1,v7,v8,v9, * V1,v7,v8,v9,v5,v2,v12
V1,v7,v8, * V1,v7,v8,v9,v5,v2,v12
V1,v7,v10 * V1,v7,v8,v9,v5,v2,v12,v10
V1,v7,v10 * V1,v7,v8,v9,v5,v2,v12,v10
V1,v7,v10,v11,v4,v6,v3 *
V1,v7,v10,v11,v4,v6,v3 *
V1,v7,v10,v11,v4,v6 *
V1,v7,v10,v11,v4 *
V1,v7,v10,v11 *
V1,v7,v10 *
V1,v7 *
V1 *
Vacía
Pasos de ejecución:
Para que la cola de prioridad ordene los vértices por distancia, podemos
hacer que la clase Vértice implemente Comparable y el método compareTo
se va a definir de acuerdo al atributo distancia de cada uno de los vértices.
Capítulo: 13 y 14
Robert Lafore (2002), “Data Structures & Algorithms in Java (2nd Edition)”,
SAMS.
Código Fuente
http://jariasf.wordpress.com/2012/03/19/camino-mas-corto-algoritmo-de-
dijkstra/
Teoría de Redes
http://docencia.udea.edu.co/regionalizacion/teoriaderedes/representacionordena
doru1.html