Está en la página 1de 9

Tema 14 – Grafos y su Implementación en Java

Índice general:
1. Conceptos básicos sobre Grafos
Tema 14 – Grafos y su 2. Representación de un Grafo: Matriz vs Listas de Adyacencia
Implementación en Java 3. Representación de un Grafo Ponderado: la clase Adyacente
Parte I 4. Representación de un Grafo ponderado y etiquetado: La clase
GrafoDEtiquetado.
5. Recorrido en Profundidad (DFS) de un Grafo
Germán Moltó
6. Recorrido en Amplitud (BFS) de un Grafo
Escuela Técnica Superior de Ingeniería Informática
Universidad Politécnica de Valencia

1 2

Objetivos Bibliografía
 Estudio de la Representación de una Relación Binaria  Libro de M.A. Weiss, “Estructuras de Datos en Java” (Adisson-
entre los Datos de una Colección mediante la estructura Wesley, 2000).
 Capítulo 14, para conceptos sobre Grafos y Grafos Dirigidos
Grafo y algunas de sus aplicaciones más significativas.
 Capítulo 22, apartado 22.2.3 para el algoritmo de Dijkstra con
 Reutilizar las Estructuras de Datos empleadas en temas Montículos de Emparejamiento
anteriores (Diccionario y Lista con Punto de Interés) y la
 Aho A.V., Hopcroft J.E., Ullman J.E. Estructuras de datos y
implementación de las operaciones de Recorrido y Algoritmos. Addison-Wesley, 1988.
cálculo de caminos mínimos sobre él (Modelos Cola y  Capítulo 6 para conceptos sobre Grafos y Grafos Dirigidos
Cola de Prioridad).
 Implementación en Java de un Grafo, que supondrá el
diseño de las clases Adyacente, Vertice, GrafoD, GrafoND
y GrafoDEtiquetado (ubicadas en el paquete grafos de
estructurasDeDatos).
3 4
Motivación Grafo Dirigido
 En ocasiones, los elementos de una colección tienen una  Un Grafo Dirigido (GD) es un Par G = (V,E)
relación entre ellos que debe ser capturada mediante la  V es un conjunto finito de Vértices (o Nodos o Puntos)
Estructura de Datos empleada.  E es un conjunto de Aristas (o Arcos) dirigidas
35
 Arista: Par ordenado de Vértices (u,v)
10 V = {1,2,3,4,5,6} |V| = 6

 Ejemplos posibles: E = { (1,2), |E| = 8


1 2 3
 Elementos: Ciudades, Aeropuertos, Computadores de una Red, (2,2), (2,4),(2,5),
Puntos de un Plano, etc. (4,1),(4,5),
4 5 6
 Se pretende modelar: (5,4),
 Rutas entre ciudades, rutas aéreas, recorridos turísticos,
(6,3) }
tareas a realizar en un proyecto, etc.

5 6

Grafo No Dirigido Grafo Etiquetado y Grafo Ponderado


 Un Grafo No Dirigido (GND) es un Par G = (V,E)  Un Grafo Etiquetado es un grafo G = (V,E) sobre el
 V es un conjunto finito de Vértices que se define una función f: E  A, dónde A es un
 E es un conjunto de Aristas no Dirigidas conjunto cuyas componentes se llaman Etiquetas.
 Arista: Par no ordenado de Vértices (u,v) = (v,u)  Un Grafo Ponderado es un Grafo Etiquetado (sus
Aristas) con números Reales.
1 2 3 V = {1,2,3,4,5,6} |V| = 6  También es posible definir la función de etiquetado para
E = {(1,2), |E| = 4 los Vértices, con lo que podemos asignar un nombre a
4 5 6 cada Vértice.
(1,5),
(2,5),
(3,6) }

7 8
Relaciones de Incidencia Relaciones de Adyacencia
 Sea G = (V,E) un Grafo Dirigido. Si (u,v) Є E, decimos  Sea G = (V,E) un Grafo. Si (u,v) Є E, decimos que el
que Incide Desde u (sale de ..) e Incide En v (llega a ..) Vértice v es Adyacente al Vértice u
• (2, 2) Є E, incide desde 2 e incide en 2 • Ejemplo con el Vértice 2 1 2 3
1 2 3
• (1, 2) Є E, incide desde 1 e incide en 2 • 2 es Adyacente a 1
• (2, 4) Є E, incide desde 2 e incide en 4 • 1 no es Adyacente a 2 4 5 6
• (2, 5) Є E, incide desde 2 e incide en 5 4 5 6
• En un Grafo no Dirigido la relación es simétrica:
• Sea G = (V,E) un Grafo no Dirigido. Si (u,v) Є E, decimos que
Incide Sobre u y v
1 2 3 • Ejemplo con el Vértice 3
1 2 3
• (1,2) Є E, ó (2,1) incide sobre 1 y 2, ó 2 y 1 • 3 es Adyacente a 6
• (2,5) Є E, ó (5,2) incide sobre 2 y 5, ó 5 y 2 4 5 6 • 6 es Adyacente a 3
4 5 6

9 10

Grado de un Vértice Caminos sobre Grafos


 El Grado de un Vértice en un Grafo no Dirigido es el  Un Camino de longitud k desde u a u’ en un grafo
número de Aristas que Inciden sobre él (Vértices G=(V,E) es una secuencia de Vértices <v0,v1,..,vk> tal que:
Adyacentes). 1 2 3  v0 = u y vk = u’
 El Grado de 2 es 2   i : 1..k : (vi-1,vi) Є E
4 5 6
 La Longitud k del Camino …
 El Grado de un Vértice en un Grafo Dirigido es la suma de:
 sin pesos es el número de Aristas
 El número de Aristas que salen de él (Grado de Salida)
 con pesos es la suma de los Pesos de las Aristas del Camino
 El número de Aristas que entran en él (Grado de Entrada)
 Si hay un Camino P desde u hasta u’, decimos que u’ es
 Ejemplos:
1 2 3 alcanzable desde u vía P
 El Grado del Vertice 2 es 5 1 2 3
 Grado de Entrada de 2 es 2  Ejemplos:
 Grado de Salida de 2 es 3 4 5 6  5 es alcanzable desde 1 vía <1,2,5>
 5 es alcanzable desde 1 vía <1,2,2,2,5> 4 5 6
 El Grado de un Grafo es el de su Vértice de máximo Grado.
11 12
Representación de un Grafo: Matriz de
Caminos Simples y Ciclos Adyacencia

 Un Camino es Simple si todos sus Vértices intermedios  Un Grafo G=(V,E) se puede representar con una Matriz
son distintos. Si los extremos son iguales es un Ciclo. de |V|x|V| boolean. Si (u,v) Є E, G[u][v] = true; sino
 Un Bucle es un ciclo de longitud 1 G[u][v] = false. 0 1 2 3 4 5
 En un Grafo Dirigido un Camino <v0,v1,..,vk> forma un  Memoria: O(|V|2) 0 false true false false false false
Ciclo si:  Tiempo de acceso: O(1) 1 false true false true true false
 v 0 = vk
 el Camino contiene al menos una Arista 2 false false false false false false
0 1 2
 Un Grafo Dirigido es Acíclico si no contiene Ciclos 3 true false false false true false
(GDA) 4 false false false true false false
 Un Ciclo en este Grafo es <1, 2, 5, 4, 1>, 1 2 3 3 4 5
5 false false true false false false
de longitud 4.
 El camino <2,2> es un bucle. 4 5 6  Esta representación consume bastante memoria.
 Conceptos similares para los Grafos No Dirigidos.  Útil para Grafos Densos (con muchas aristas).
13 14

Cuestiones Rápidas: Representación Representación de un Grafo: Listas de


con Matriz de Adyacencia Adyacencia
1. ¿Cómo saber si el grafo tiene bucles?  Un Grafo Dirigido G=(V,E) se suele representar con un
2. ¿Cómo saber el número de vértices? array de |V| Listas de Vértices: G[v] es una Lista de los
3. ¿Cómo saber si hay algún vértice sin adyacentes? Vértices Adyacentes a v (v Є V).
 Memoria: O(|V|+|E|)
4. ¿Cómo calcular el número de adyacentes de un vértice?  Tiempo de acceso: O(Grado de salida de G)
5. ¿Cómo sería la matriz de adyacencia de un grafo no 2 |X
1
dirigido?
2 2| 4| 5 |X
6. ¿Cómo representar un Grafo con aristas ponderadas 1 2 3
3 X
usando una matriz de adyacencias?
4 5 6 4 1| 5 |X
5 4 |X
6 3 |X

15 16
Representación de un Grafo: Listas de
Adyacencia Propuesta de Implementación de Grafos
 Un Grafo No Dirigido G=(V,E) se representa con un  Grafo: Contiene los métodos
Grafo comunes a cualquier
array de |V| Listas de Vértices: G[v] es una Lista de los <<abstract>>
Vértices Adyacentes a v (v Є V) implementación de un Grafo.
 Memoria: O(|V|+2*|E|)  GrafoD: Grafo dirigido con
 Tiempo de acceso: O(Grado de G) aristas ponderadas.
GrafoD
1 2| 5 |X  GrafoND: Grafo no dirigido
1 2 con aristas ponderadas
1 3 2 1| 5| 4| 3 |X

3
 GrafoDEtiquetado: Grafo
5 4 2| 4 |X GrafoDEtiquetado
dirigido con aristas
4 5| 2| 3 |X
ponderadas y vértices
5 1| 2| 4 |X GrafoND etiquetados.

17 18

La clase Java Grafo (I) La clase Java Grafo (II)


public abstract void insertarArista(int i, int j);
 Sobre la clase Grafo:
public abstract void insertarArista(int i, int j, double p);
 Su implementación irá creciendo conforme veamos public abstract ListaConPI<Adyacente> adyacentesDe(int i);
métodos de recorrido, cálculo de caminos mínimos, public String toString(){
etc. String res = "" ;
for (int i = 1 ; i <= numVertices() ; i++) {
package librerias.estructurasDeDatos.grafos;
res += "Vértice: " + i;
public abstract class Grafo {
ListaConPI<Adyacente> l = adyacentesDe(i);
public Grafo() { ... }
res += (l.esVacia()) ? " sin Adyacentes " : " con Adyacentes: ";
public abstract int numVertices(); for (l.inicio(); !l.esFin() ; l.siguiente()) res += l.recuperar() + " ";
public abstract int numAristas(); res += "\n"; Implementa el método
public abstract boolean existeArista(int i, int j); } return res; toString. Salida:
public abstract double pesoArista(int i, int j); } Vértice 1 con adyacentes 2 3
Vértice 2 sin adyacentes

19 20
Implementación de un Grafo Dirigido
La clase Java Adyacente Ponderado: La Clase GrafoD
package librerias.estructurasDeDatos.grafos;  GrafoD representa un Grafo
class Adyacente{  de Vértices sin Etiquetar
int destino;  de Aristas con Pesos, Tripletes de int (origen, destino, coste)
double peso;
 Mediante Listas de Adyacencia (array de |V| ListaConPI
Adyacente(int codAdy, double p){ destino=codAdy; peso = p; }
de Adyacentes)
public String toString(){ return destino + “(”+ peso + “)”; } 2 1 (2,3) |X
} 2 (2,2) | (4,8) | (5,7) |X
3
1 2 3
8 3 X
 La clase Adyacente no se hace pública puesto que únicamente se 7 7 7
utilizará dentro del paquete grafos (acceso friendly únicamente 3 4 (1,7) |
4 5 6 (5,3) |X
para el resto de clases del paquete). 3 5 (4,3) |X
6 (3,7) |X

21 22

La clase Java GrafoD (I) La clase Java GrafoD (II)


package librerias.estructurasDeDatos.grafos; public int numVertices() { return numV;}
import librerias.estructurasDeDatos.modelos.ListaConPI; public int numAristas() { return numA; }
import librerias.estructurasDeDatos.lineales.LEGListaConPI; public boolean existeArista(int i, int j) {
public class GrafoD extends Grafo { ListaConPI<Adyacente> l = elArray[i]; boolean esta=false;
protected int numV, numA; for (l.inicio(); !l.esFin()&& !esta; l.siguiente())
protected ListaConPI<Adyacente> elArray[]; if (l.recuperar().destino==j) esta =true;
return esta;
@SuppressWarnings("unchecked") Por convenio, los vértices se numeran }
desde 1..N y se almacenan en las
public GrafoD(int numVertices){ posiciones 1..N del array. public double pesoArista(int i, int j) {
numV = numVertices; numA=0; ListaConPI<Adyacente> l = elArray[i];
elArray = new ListaConPI[numVertices+1]; for (l.inicio(); !l.esFin(); l.siguiente())
for (int i=1; i<=numV; i++)elArray[i]= newLEGListaConPI<Adyacente>(); if (l.recuperar().destino==j) return l.recuperar().peso;
} return 0.0;
}
23 24
La clase Java GrafoD (III) Prueba de la clase GrafoD
public void insertarArista(int i, int j) { public static void main(String args[]){
insertarArista(i,j,1); GrafoD g = new GrafoD(6);
} 3
g.insertarArista(1, 2, 3); 1 2 3
g.insertarArista(1, 5, 8); 9 5
8
public void insertarArista(int i, int j, double p) { g.insertarArista(2, 5, 9);
4 5 6
if ( !existeArista(i,j) ) { elArray[i].insertar(new Adyacente(j,p)); numA++; } g.insertarArista(3, 6, 5);
} System.out.println(“El grafo es: "+g.toString());
System.out.println("existeArista(3,1) = " + g.existeArista(3,1));
public ListaConPI<Adyacente> adyacentesDe(int i) {return elArray[i];} ListaConPI<Adyacente> l = g.adyacentesDe(1);
System.out.println(“Los adyacentes al vértice 1 son: ");
} /* Fin de la clase GrafoD */ for (l.inicio(); !l.esFin(); l.siguiente()) {
System.out.println(“(1, " + l.recuperar().destino + ")");
}
}

25 26

Implementación de Grafo Dirigido Ponderado con


La clase Java GrafoND Vértices Etiquetados: Clase GrafoDEtiquetado
package librerias.estructurasDeDatos.grafos;
import librerias.estructurasDeDatos.modelos.ListaConPI;  La clase GrafoDEtiquetado representa un Grafo
public class GrafoND extends GrafoD {  de Vértices con Etiquetas (dato de tipo objeto), i.e. Pares
public GrafoND(int numVertices) { super(numVertices); } (etiqueta/dato, nº vértice)
 de Aristas con Pesos
¿Cómo se implementaría el
método insertarArista?  Mediante Listas de Adyacencia (array de |V| ListaConPI
public void insertarArista(int i, int j, int p) { No se permiten bucles.
de Adyacentes) 1 (v1) (2,3) |X
if ( !existeArista(i,j) && i != j) {
elArray[i].insertar(new Adyacente(j,p)); 2 2 (v2) (2,2) | (4,8) | (5,7) |X
elArray[j].insertar(new Adyacente(i,p)); 3 3 (v3) x
v1 v2 v3
}
8 4 (v4) (1,7) |
numA++; 7 7 7 (5,3) |X
3
} v4 v5 v6 5 (v5) (4,3) |X
} /* Fin de la clase GrafoND */ 3
6 (v6) (3,7) |X
27 28
Correspondencia entre Etiquetas de
Vértice y su Código La clase Java GrafoDEtiquetado (I)
package librerias.estructurasDeDatos.grafos;
 El constructor del Grafo especifica los vértices de los que va a
constar el grafo. import librerias.estructurasDeDatos.modelos.*;
 Los vértices ya existen al crear el Grafo (aunque sin etiquetar). import librerias.estructurasDeDatos.hash.TablaHashDiccionario;
import librerias.excepciones.ElementoNoEncontrado;
 Para etiquetar un vértice, se utiliza el método:
 public void etiquetarVertice(int codigo, E etiqueta) import java.util.ArrayList;
 Para obtener el código de un vértice a partir de su etiqueta, public class GrafoDEtiquetado<E> extends GrafoD{
utilizamos un Diccionario<E,Integer>. E etiquetas[];
Diccionario<E, Integer> dicVertices;
Índice Nombre @SuppressWarnings("unchecked")
D C 10 1 D public GrafoDEtiquetado(int numVertices) {
Listas de super(numVertices);
A B 12 2 C
Adyacencia de
D B 23 3 A etiquetas = (E[]) new Object[numVertices+1];
cada
A D 87 dicVertices = new TablaHashDiccionario<E, Integer>(numVertices);
4 B Vértice
E D 43 }
6 E
29 30

La clase Java GrafoDEtiquetado (II) La clase Java GrafoDEtiquetado (III)


public boolean existeArista(E i, E j) { public void etiquetarVertice(int codigo, E etiqueta) {
return existeArista(obtenerCodigo(i), obtenerCodigo(j)); etiquetas[codigo] = etiqueta;
} dicVertices.insertar(etiqueta, codigo);
public double pesoArista(E i, E j) { }
return pesoArista(obtenerCodigo(i), obtenerCodigo(j)); public E obtenerEtiqueta(int codigo) {
} return etiquetas[codigo];
public void insertarArista(E i, E j) { }
insertarArista(obtenerCodigo(i), obtenerCodigo(j)); public int obtenerCodigo(E etiqueta) {
} int codigo;
public void insertarArista(E i, E j, double p) {
try {
insertarArista(obtenerCodigo(i), obtenerCodigo(j), p);
codigo = dicVertices.recuperar(etiqueta).intValue();
}
} catch (ElementoNoEncontrado e) { codigo = -1; }
public ListaConPI<Adyacente> adyacentesDe(E i) {
return codigo;
return adyacentesDe(obtenerCodigo(i));
}
}
31 32
Prueba de la clase GrafoDEtiquetado
public static void main(String args[]){
GrafoDEtiquetado<Persona> g = new GrafoDEtiquetado<Persona>(3);
Persona jane = new Persona("1123F","Jane Doe",25);
Persona john = new Persona("5656M","John Doe",46);
Persona paul = new Persona("8372G", "Paul Carlson", 21); Paul
(3)
g.etiquetarVertice(1,jane); John
g.etiquetarVertice(2,john); (2) 7 3
g.etiquetarVertice(3,paul); Jane
10
g.insertarArista(jane, john, 10); (1)
g.insertarArista(jane, paul, 7);
g.insertarArista(paul, jane, 3);
Grafo de afinidad ([0..10]) que siente
System.out.println("Grafo: " + g); una persona hacia las de su red social.
}
33

También podría gustarte