Estructura de Datos
Tema 5:
Grafos (clase 1)
UNIVERSIDAD NACIONAL DE LA PATAGONIA AUSTRAL Unidad Académica Río Gallegos
Docente: Lic. Héctor Reinaga
Indice
Introducción Concepto Grafos Clasificación
Dirigidos
No dirigidos
Etiquetados
Terminología de Grafos:
Bucle, Sucesor, Predecesor, Grado, Vértice aislado, Camino, Longitud,
Camino simple, Ciclo, Cadena, Conectividad. TDA Grafos
Implementación
Matriz de adyacencia Listas de adyacencia
Operaciones
Recorrido en profundidad
Grafos Estructura de Datos 2017 2
Introducción
Estructuras de datos estudiadas:
TDA lineales:
Listas, pilas, colas.
Colección de elementos donde cada uno
tiene un elemento siguiente y uno anterior.
Las relaciones entre los nodos de información son lineales.
Todos los nodos tienen un único antecesor, excepto el
primero que no tiene antecesor.
Todos los nodos tienen un único sucesor, excepto el último
que no tiene sucesor. Lista
Pila Cola
Introducción
Estructuras de datos estudiadas:
TDA no lineales:
árboles y sus variantes
Cuando se está en presencia de relaciones no lineales de tipo jerárquica, se utilizan los árboles.
Un nodo puede tener más de un sucesor.
Cada nodo tiene un único padre, exceptuando al nodo raíz del árbol, que no
tiene padre.
…
Árbol Binario:
Un nodo solo puede apuntar a 2 nodos.
Un nodo es apuntado a lo sumo por 1 nodo.
A
D
E F
G
Grafos Estructura de Datos 2017 4
Introducción
Ahora generalizamos la estructura de árbol
permitir que un elemento pueda tener más de un elemento anterior y
siguiente.
En ocasiones, se requiere tener acceso a un nodo determinado a partir de más de un nodo de la estructura. Existen varios caminos entre un nodo y otro.
Ejemplos:
Una red hidráulica,
Caminos entre ciudades,
Ruta aérea
Red de computadoras, etc.
Ciudad A
Ciudad B
Ciudad C Ciudad F
Ciudad D
Ciudad E
Concepto: grafos
Conceptos:
Un grafo es una estructura donde cada elemento pueda
tener cero, uno o muchos elementos anteriores y siguientes.
Un grafo es un TDA que representa un conjunto finito N de
nodos, llamados vértices, relacionados entre sí por un conjunto R de aristas/arcos.
Ejemplo:
Grafo
5 vértices y 6 arcos. Vértices del Grafo
N ={ A, B, C, D, E } Arcos del Grafo
R={(A, A), (A, B), (A, D), (A, C), (D, C), (C, E)} A
B
D C
Grafos Estructura de Datos 2017 6
Clasificación
Es importante recordar que un mismo grafo puede tener diferentes representaciones gráficas.
Ejemplo:
Dos representaciones del mismo grafo
G = ({a,b,c,d,e,f},{{a,b},{a,e},{a,f}{e,f},{b,c},{c,d},{e,d},{d,f}})
Clasificación
Básicamente, podemos clasificar los grafos en 4 tipos
dependiendo de dos criterios (dirigido y etiquetado)
Grafo dirigido. Es aquel cuyas aristas forman pares
ordenados (u, v).
Grafo no dirigido. Es aquel cuyas aristas no son pares
ordenados. (u,v)=(v,u)
Grafo etiquetado o valorado. Cuando se asocia
información a cada arista de un grafo.
Grafo no etiquetado. Cuando no se asocia ninguna
Grafos Estructura de Datos 2017 8
Grafos dirigidos
Un grafo es dirigido cuando los arcos tienen dirección.
Dado un arco (A,B) del conjunto R, se dice que
A es el origen B es el destino
En este caso, las aristas se llama arcos y se representan como
pares para indicar el orden:
V = { A,B,C,D,E}
R={(A, A), (A, B), (A, D), (A, C), (D, C), (C, E)}
También conocido como digrafos
A
B
D C
E
Grafos no dirigidos
Un grafo es no-dirigido cuando los arcos no tienen
dirección.
Es irrelevante el sentido de los arcos.
El arco que los relaciona aparece una sola vez en el
conjunto R de arcos del grafo.
Si el grafo es no orientado, al arco se le llama
arista.
A
B
D C
Grafos Estructura de Datos 2017 10
Grafos etiquetados
Los vértices y arcos (o aristas) de un grafo pueden
ser elementos con información adicional unida a
ellos.
Tales grafos se llaman grafos etiquetados o
ponderados.
Ejemplo:
94
120 95
175 1
2
3
4
101
154 Ciudad2
Ciudad4
Ciudad3 Ciudad1
Grafos Estructura de Datos 2017 12
Definiciones básicas
Se dan a continuación una serie de conceptos definidos sobre
grafos dirigidos (digrafos).
Para ejemplificar los mismos usaremos el siguiente grafo:
Terminología de Grafos
Bucle
Arco de la forma (x, x), es un arco que tiene por origen y destino al
mismo vértice.
Ejemplo:
Grafos Estructura de Datos 2017 14
Terminología de Grafos
Sucesor/Adyacente
Se dice que el nodo y es sucesor o adyacente del nodo x, si existe un arco
que tenga por origen a x y por destino a y, es decir sí el arco (x, y) A.
Al conjunto de nodos sucesores de x lo denotaremos con S(x).
Ejemplo:
Conjunto de sucesores de v4
Existen dos arcos que tienen como origen a v4: (v4, v3) y (v4, v5) S(v4) = {v3, v5}
Conjunto de sucesores de v2
Existen cuatro arcos que tienen como origen a v2: (v2, v2), (v2, v3), (v2, v4) y (v2, v5)
S(v2) = {v2, v3, v4, v5}
Que pasa con v3 y v6?
conjunto de sucesores es vacío S(v3) = S(v6) =
Terminología de Grafos
Predecesor/Incidente
Se dice que el nodo y es predecesor del nodo x, si existe un arco que tenga
por origen a y y por destino a x, es decir sí el arco (y, x) A.
Al conjunto de nodos predecesores de x lo denotaremos con P(x).
Ejemplo:
Conjunto de predecesores de v4:
El vértice v4 es destino de tres arcos (v1, v4), (v2, v4) y (v5, v4) P(v4) = {v1, v2, v5}
Conjunto de predecesores de v3:
El vértice v4 es destino de dos arcos (v2, v3) y (v4, v3)
P(v2) ={v2, v4}
Que pasa en el caso v2?
Grafos Estructura de Datos 2017 16
Terminología de Grafos
Grado:
El grado de un vértice, es la suma de los grados de entrada y de
salida del vértice
El grado de entrada de un vértice n es el número de arcos que llegan
a él: g-(x) = |P(x)|
El grado de salida de un vértice n es el número de arcos que sale de
él: g+(x) = |S(X)|
Grado del nodo x: g(x) = |P(x) S(X)|
Ejemplo:
Cálculo de grados para v4: g-(v4) = |{v1, v2, v5}| = 3 g+(v4) = |{v3, v5}| = 2
g(v4) = |{v1, v2, v5} {v3, v5}| = 5
Terminología de Grafos
Vertice aislado:
Se dice que un vértice x es aislado sí el grado es igual a cero, es decir,
g(x)=0.
Ejemplo:
Vértice v6:
Único vértice aislado
g(v6) = |P(v6) S(v6)| = || = 0
Que pasa con el vértice v7?
no puede ser considerado como aislado, dado que al tener un bucle su grado es
1.
En general, para que un vértice se considere aislado no tiene que ser origen
Grafos Estructura de Datos 2017 18
Terminología de Grafos
Camino:
Existe un camino del vértice x al vértice y, si podemos llegar de x a y siguiendo los
arcos y en el sentido en que éstos están.
Ejemplo:
Camino de v1 a v5
Dos caminos:
(v1, v2), (v2, v4) y (v4, v5)
(v1, v4) y (v4, v5).
Longitud:
La longitud del camino es igual a la cantidad de arcos que lo forman, o número de
vértices menos 1.
Ejemplo:
Camino de v1 a v5
Longitud es 3
Camino de longitud nula:
V3
Camino de longitud 4:
(V5,V1), (V1,V2), (V2,V4), (V4,V3)
Terminología de Grafos
Camino simple
si no pasa dos veces por un mismo vértice. Ejemplo:
La secuencia <v1, v2, v4, v5, v4, v5, v1>, es simple? No
La secuencia <v1, v4, v3> Si
Ciclo
es un camino simple de longitud mayor que 1, en donde coinciden
los vértices primero y último.
Ejemplo:
Grafos Estructura de Datos 2017 20
Terminología de Grafos
Cadena:
Concepto similar a camino
Existe una cadena del vértice x al vértice y, si podemos llegar de x a y siguiendo los
arcos, sin tener en cuenta el sentido de los mismos.
Ejemplo:
Camino de origen V3
Existe camino?
No
Existen cadenas con inicio en ese vértice?
Si, por ejemplo v3- v4-v5.
Longitud de la cadena
Cantidad de aristas/arcos que la forman
Cadena simple
si no pasa dos veces por un mismo vértice.
Circuito
es una cadena simple de longitud mayor que 1, en donde coinciden los vértices primero y último.
Resumen:
Todo camino es una cadena, pero no toda cadena es un camino.
Todo ciclo es un circuito, pero no todo circuito es un ciclo.
Terminología de Grafos
Cadena:
Ejemplo:
Las siguientes secuencias son ejemplos de cadena: <v1, v2, v4, v5>, <v2, v1, v4>, <v3, v2, v4, v5>, <v2, v2> Las siguientes secuencias además de cadenas son circuitos:
<v5, v2, v4, v5>, <v1, v2, v4, v5, v1>, <v3, v4, v2, v3>. Existe cadena en v6?
No porque v6 es un vértice aislado. Existe cadena en v7?
Grafos Estructura de Datos 2017 22
Conectividad
Grafo conectado/conexo
Cuando existe siempre un camino que une 2 vértices cualquiera.
Grafo completo/fuertemente conectado
Cuando cada vértice está conectado con todos y cada uno de los
nodos restantes (cada nodo es adyacente a los demás).
Grafo conectado
No fuertemente conectado
no existe camino entre v3 y v2
Grafo conectado
Fuertemente conectado
Grafo NO conectado
no existe camino entre v5 y v3 Por lo tanto, no fuertemente
conectado
TDA Grafos
Grafos Estructura de Datos 2017 24
TDA Grafos
Como tipo de dato abstracto un grafo G = (V, A)
consta de:
conjunto de vértices V
conjunto de arcos A
operaciones actuando sobre estos dos conjuntos.
Se definen tres clases:
Grafos
Vertice
objeto compuesto de una etiqueta
Arco
objeto compuesto de dos vértices y opcionalmente de una etiqueta.
TDA Grafos
Algunas operaciones sobre grafos:
Construir un grafo.
Verificar si un grafo está vacío o no. Insertar vértices y arcos.
Eliminar vértices y arcos.
Dados dos vértices, determinar si son adyacentes.
Dado un vértice, determinar cuáles vértices son adyacentes
a él.
Dados dos vértices, determinar un camino de longitud k
entre ellos.
Dado un arco, determinar vértices incidentes a él. Determinar si el grafo es cíclico.
Grafos Estructura de Datos 2017 26
Implementación
Para representar un grafo se pueden emplear
varias estructuras de datos.
La selección apropiada depende de las
operaciones que se realizarán sobre los
vértices y sobre los arcos del grafo.
Vamos a ver dos posibles implementaciones:
Mediante matrices de adyacencia. (estática)
Mediante listas de adyacencia. (dinámica)
Matriz de adyacencia
La representación matricial permite establecer si hay
relación entre cada vértice del grafo y los demás.
Para ello, se utiliza una matriz cuadrada.
Se utiliza un arreglo bidimensional.
Los elementos de la matriz son booleanos.
Si el elemento (i, j) es verdadero, existe un arco que va del
vértice i al vértice j y,
si el elemento (i, j) es falso, no existe arco del vértice i al
vértice j.
Si el grafo es no dirigido.
Si existe el arco del vértice i al vértice j, entonces existe el
Grafos Estructura de Datos 2017 28
Matriz de adyacencia
Ejemplo:
Grafo dirigido y no dirigido1 2 3 4
F T F F
F F F T
F T F F
F F T F
1 2 3 4
T F T T
F T F F
F T F T
F T T F
1 2 3 4 1 2 3 4
Matriz de adyacencia
La implementación básica para un grafo dirigido es la siguiente:
public class Graph {
private Vertex[] vertices; private int vertexPosition; private boolean[][] edges; private int vertexQuantity; Graph(int quantity) { vertexQuantity=quantity; vertices=new Vertex[vertexQuantity]; vertexPosition=0; edges=new boolean[vertexQuantity][vertexQuantity]; }
public void insertVertex(Object element) {
vertices[vertexPosition]=new Vertex(); vertices[vertexPosition].setElement(element); vertexPosition++;
}
public void insertEdge(Object originElement, Object finishElement) {
int originPosition=getVertexOrder(originElement); int finishPosition=getVertexOrder(finishElement); edges[originPosition][finishPosition]=true; }
private int getVertexOrder(Object element) {
int position=0, order=-1; boolean found=false;
Grafos Estructura de Datos 2017 30
Matriz de adyacencia
La implementación básica para un grafo dirigido (continúa):
public class Vertex {
private Object element; Vertex()
{ element=null; }
public Object getElement() {
return element; }
public void setElement(Object element) {
this.element=element; }
}
Matriz de adyacencia: análisis
Ventajas
Representación y operaciones muy sencillas.
Eficiente para el acceso a una arista dada
O(1)
.
Inconvenientes
El principal, es que se necesita un espacio de
O(n
2)
aunque el grafo tenga muy pocas aristas.
El número de nodos del grafo no puede cambiar.
Grafos Estructura de Datos 2017 32
Lista de adyacencia
En esta estructura de datos la idea es asociar a cada vértice i
del grafo una lista que contenga todos aquellos vértices j que sean adyacentes a él.
De esta forma sólo reservará memoria para los arcos
adyacentes a i y no para todos los posibles arcos que pudieran tener como origen i.
El grafo se representa por un vector de n componentes.
En caso de que el grafo sea etiquetado, habrá que añadir un
segundo campo para mostrar el valor de la etiqueta.
Lista de adyacencia
Grafos Estructura de Datos 2017 34
Lista de adyacencia
Ventajas
Útil cuando un grafo tiene muchos vértices y
pocas aristas/arcos.
Desventajas
Representación más compleja.
Es ineficiente para encontrar las aristas que llegan
a un nodo.
Puede llevar un tiempo
O(n)
determinar si existe
un arco del vértice i al vértice j, ya que puede
haber n vertices en la lista de adyacencia asociada
al vértice i.
Lista de adyacencia
La implementación básica para un grafo dirigido es la siguiente:
public class Graph { private Vertex[] vertices; private int vertexPosition; private int vertexQuantity; Graph(int quantity) { vertexQuantity=quantity; vertices=new Vertex[vertexQuantity]; vertexPosition=0;
}
public void insertVertex(Object element) { vertices[vertexPosition]=new Vertex(); vertices[vertexPosition].setElement(element); vertexPosition++;
}
public void insertEdge(Object originElement, Object finishElement) { int originPosition=getVertexOrder(originElement);
Edge edge=vertices[originPosition].getEdge(); Edge newEdge=new Edge();
newEdge.setPosition(getVertexOrder(finishElement)); if(edge==null) vertices[originPosition].setEdge(newEdge); else { while(edge.getEdge()!=null) edge=edge.getEdge(); edge.setEdge(newEdge);
private int getVertexOrder(Object element) { int position=0, order=-1; boolean found=false;
Grafos Estructura de Datos 2017 36
Lista de adyacencia
La implementación básica para un grafo dirigido (continúa):
public class Vertex { private Object element; private Edge edge;
Vertex() { element=null; edge=null; }
public Object getElement() { return element; }
public Edge getEdge() { return edge; }
public void setElement(Object element) { this.element=element;
}
public void setEdge(Edge edge) { this.edge=edge;
} }
public class Edge { private int position; private Edge edge; Edge() {
position=0; edge=null; }
public int getPosition() { return position; }
public Edge getEdge() { return edge; }
public void setPosition(int position) { this.position=position; }
public void setEdge(Edge edge) { This.edge=edge; }
}
Operaciones sobre Grafos
Grafos Estructura de Datos 2017 38
Recorridos
La operación de recorrer un grafo consiste
En comenzar de un vértice determinado, y
visitar todos aquellos vértices que son accesibles desde él en
un determinado orden.
Se siguen dos estrategias:
el recorrido en profundidad (DFS: Depth First Search): Equivalente a un recorrido en preorden de un árbol recorrido en anchura (BFS: Breadh First Search).
Equivalente a recorrer un árbol por niveles
El recorrido puede ser tanto para grafos dirigidos
como no dirigidos.
Es necesario llevar una cuenta de los nodos visitados
y no visitados.
Recorrido en profundidad
Estrategia que emplea: primero visita los hijos y
luego los hermanos.
1. Visitar nodo
2. Seleccionar adyacente no visitado
3. Recorrer en profundidad el nodo no visitado
4. Volver al punto 2
Es similar al recorrido preorden de los árboles.
Suponemos la existencia de un conjunto (visitados)
para ir almacenando los vértices del grafo visitados.
En principio el conjunto de vértices visitados estará
vacío.
Grafos Estructura de Datos 2017 40
Recorrido en profundidad
La implementación del algoritmo es la siguiente:
public void depthFirstSearch(Object element) { Vector visited=new Vector(vertexQuantity); depthFirst(getVertexOrder(element), visited); }
private void depthFirst(int element, Vector visited) { System.out.print(vertices[element].getElement()+" "); visited.addElement(new Integer(element));
Enumeration adjs=adjacents(new Integer(element)); while(adjs.hasMoreElements()) {
Integer adjsOther=(Integer)adjs.nextElement(); if(!visited.contains(adjsOther))
depthFirst(adjsOther.intValue(), visited);
} }
Recorrido en profundidad
Ejemplo:
A
T H
B
D
C
R
Se Muestra:
Pila
D D
B C
C
R R
H
H
A T
Grafos Estructura de Datos 2017 42
Recorrido en profundidad
Complejidades
Matrices de adyacencias:
Caso mejor O(n)
Caso peor O(n²)
Lista de adyacencias
Caso mejor: O(1)
Caso peor : O(n²)
Recorrido en anchura
Estrategia que emplea:
Primero visita los hermanos y luego los hijos.
Pasos:
Primero se visita nodo v.
Luego se visitan todos sus adyacentes. (hermanos) Luego los adyacentes de estos (hijos) y así sucesivamente.
El algoritmo utiliza una cola de vértices.
Se utiliza un conjunto (visitados) para ir almacenando los
vértices del grafo por los que se va pasando.
En una cola se mantienen los vértices adyacentes que se han
obtenido a partir de los vértices visitados y cuyos adyacentes aún restan por explorar.
Operaciones básicas:
Sacar un nodo de la cola.
Grafos Estructura de Datos 2017 44
Recorrido en anchura
La implementación del algoritmo es la siguiente:
public void breadhFirstSearch(Object element) { breadhFirst(getVertexOrder(element)); }
private void breadhFirst(int element) { Vector visited=new Vector(vertexQuantity); Queue explore=new Queue();
explore.insert(new Integer(element)); visited.addElement(new Integer(element)); do { Integer vertexOther=(Integer)explore.delete(); System.out.print(vertices[vertexOther.intValue()].getElement()+" "); Enumeration adjs=adjacents(vertexOther); while(adjs.hasMoreElements()) { Integer adjsOther=(Integer)adjs.nextElement(); if(!visited.contains(adjsOther)) { explore.insert(adjsOther); visited.addElement(adjsOther); } } } while(!explore.isEmpty()); }
Recorrido en anchura
Ejemplo:
A T H B D C R D Cola Se Muestra: DB C
B C
C H H R
H
R A
R A
T
T
Grafos Estructura de Datos 2017 46
Recorrido en anchura
Para ambos recorridos será necesario el método adyacentes
(para lista de adyacencia).
private Enumeration adjacents(Integer element) { Vector vertices=new Vector();
Edge position=vertices[element.intValue()].getEdge();
while(position != null) {
vertices.addElement(new Integer(position.getPosition())); position=position.getEdge();
}
return vertices.elements(); }
Recorrido en anchura
Complejidades
Matrices de adyacencias
Caso mejor O(n)
Caso peor O(n²)
Lista de adyacencias
Caso mejor O(1)
Grafos Estructura de Datos 2017 48
Consultas…
Próximas clases
Clases prácticas:
Viernes 13/10 de 18 a 20 hs.
Clase de teoría: