Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Lectura 2
Unidad 2: Grafos
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.
Caminos
Un camino es una secuencia de vértices w1,..,wN donde (wi,wi+1) ε E,
para 1≤ i < N.
2.1- 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
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 13 – Ejemplo DFS - Fuente: Libro “Data Structures and Algorithms in Java” – Robert
Lafore, pág. 625.
Algoritmo de Dijkstra
“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.
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,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
www.uesiglo21.edu.ar