Está en la página 1de 43

Grafos

Estructura de Datos

Federico Cirett Galán


federico.cirett@unison.mx
Los puentes de Königsberg
Los puentes de Königsberg
A

C
Los puentes de Königsberg

Grafos
Un grafo es un set de vértices y de conexiones (arcos o aristas)

• Los arcos describen la relación entre los vértices.

• G = (V,E)

Guaymas Obregón Navojoa

Hermosillo

Nogales
Aplicaciones
• Mapas

• Moléculas

• Horarios

• Redes computacionales

• Páginas web (hipertexto)


Grafos
• Definición formal de grafo:

• Un grafo se define como G = (V,E)

• Donde:

• V = Un conjunto finito de vértices

• E = Es un set de arcos o conexiones (entre pares


de vértices)
Grafos no dirigidos
• (Undirected graphs)

• Cuando los arcos o conexiones no contienen


dirección, el grafo es no-dirigido
V = { Hermosillo,
Nogales, Guaymas,
Obregón, Navojoa}

Guaymas Obregón Navojoa E = { (Hermosillo,


Nogales), (Hermosillo,
Guaymas), (Guaymas,
Obregón), (Obregón,
Navojoa}

Hermosillo Nogales
Grafos dirigidos
• Directed graphs

• Cuando los arcos tienen dirección, el grafo es


dirigido.
Hotel
Casa de San
la Cultura Sebastián

V = { Unison, Hospital Infantil, IMSS#2, Casa de la


Cultura, Hotel San Sebastián}
Hospital
Unison Infantil E = { (Unison, Hospital Infantil), (Unison, IMSS#2),
(Unison, Casa de la Cultura), (Hospital
Infantil,IMSS#2),
(Hospital Infantil, Unison), (IMSS#2, Unison), (IMSS#2,
Hospital Infantil), (Casa de la Cultura, Hotel San
IMSS #2 Sebastián), (Hotel San Sebastián), (Casa de la
Cultura)}
Grafos
• Los árboles son un caso especial de grafo.

3 7

2 4 6

V = { 2, 3, 4, 5, 6, 7}

E = { (5,3),(5,7),(3,2), (3,4), (7,6)}


Grafos (Terminología)
• Nodos Adyacentes: Dos nodos son adyacentes
(muy próximos o unidos) si los conecta un arco

5 es adyacente a 3
5 3 3 es adyacente desde 5

5 es adyacente a/desde 3
5 3 3 es adyacente desde/a 5

Dos vértices son adyacentes si una arista (arco) los une.

Adyacencia: dos aristas (arcos) son adyacentes si tienen un vértice en común.


Grafos (Terminología)
• Path (camino, sendero, trayectoria): Una secuencia
de vértices que conectan dos nodos en un grafo.

• La longitud de un Path es el número de arcos (edges)


que conforman el camino.
1 2

un Path desde 1 a 4:
< 1-2, 2-3, 3-4 >

otro Path desde 1 a 4:


3 4 < 1-2, 2-4 >
Grafos (Terminología)
• Grafo completo: Un grafo en el que cada vértice
está directamente conectado a cada uno de los
demás vértices
1

1 2

2 3

3 4 4

Grafo dirigido completo Grafo no-dirigido completo


Grafos (Terminología)
• Como calcular el número de arcos en un:

Grafo dirigido completo

1 2

E = V * (V-1)

3 4

Grafo dirigido completo


Grafos (Terminología)
• Como calcular el número de arcos en un

Grafo no-dirigido completo

E = V * (V-1) / 2
2 3

Grafo no-dirigido completo


Grafos (Terminología)
• Grafos ponderados o etiquetados (Weighted
graph): Grafo donde cada arco tiene un valor.

4
Hotel
Casa de San
6 la Cultura Sebastián
4

5 8
7 Hospital
Unison Infantil
4
3

4 IMSS #2 6
Grafos

• Implementación:

• Basado en Arreglos

• Basado en Listas Ligadas


Grafos
• Representación basada en Arreglos:

• Usar un arreglo de 1 dimensión para Vértices

• Usar un arreglo bi-dimensional (Matriz) para


arcos (conexiones) 4
Hotel
Casa de San
6 la Cultura Sebastián
4

5
8
7 Hospital
Unison Infantil
4
3

4 IMSS #2 6
Grafos
• Implementación en base a Arreglos
VÉRTICES ARCOS (EDGES)

Hotel San 4 4
4
Sebastián

Casa de la 3 5 4
3
Cultura
2 4 4
2 IMSS#2
1 7 6
Hospital
1
Infantil 0 8 3 6

0 Unison 0 1 2 3 4
Grafos
• Implementación basada en Arreglos

• Uso de memoria:

• O(V+V2) = O(V2)

• Usar preferentemente cuando el grafo es denso

• Ventaja:

• Se puede determinar rápidamente si existe un arco entre dos vértices

• Desventaja:

• No es posible determinar rápidamente si un nodo es adyacente a los


demás.
Grafos
• Grafos basados en arreglos

#define MAXVERTICES 6

/* --------- Grafo --------- */

typedef struct GrafoArreglo

int vertices[MAXVERTICES];

int edges[MAXVERTICES][MAXVERTICES];

} GRAPH;
Grafos
• Grafos basados en arreglos

void insert_edge(GRAPH *g, int from, int to, int weight)

if (g != NULL)

if ( (from > 0) && (from < MAXVERTICES) )

if ( (to > 0) && (to < MAXVERTICES) )

g->edges[from][to] = weight;

}
Grafos
• Grafos basados en arreglos / Revisar si existe un arco entre dos vértices

int existe_edge(GRAPH *g, int from, int to)

if (g != NULL)

if ( (from > 0) && (from < MAXVERTICES) )

if ( (to > 0) && (to < MAXVERTICES) )

if(g->edges[from][to] > 0)

return TRUE;

}
Grafos
• Representación basada en Listas ligadas:

• Usar una lista ligada para los Vértices

• Usar una lista ligada para cada vértice que tenga arcos
(conexiones) hacia otros vértices
4
Hotel
Casa de San
6 la Cultura Sebastián
4

5
8
7 Hospital
Unison Infantil
4
3

4 IMSS #2 6
Grafos
• Implementación en base a Listas Ligadas
VÉRTICES ARCOS (EDGES)

4:Hotel San
3:4
Sebastián

3:Casa de la Cultura 0:6 4:4

2:IMSS#2 0:3 1:6

1:Hospital Infantil 2:4

0:Unison 1:7 2:4 3:5


Grafos
• Implementación basada en Listas Ligadas

• Uso de memoria:

• O(V+E)

• En grafos dispersos, el uso de memoria es O(V), pues E=O(V)

• En grafos densos, el uso de memoria es O(V2), pues E= O(V2)

• Usar preferentemente cuando el grafo es disperso o esparso

• Ventaja:

• Se puede determinar rápidamente los vértices adyacentes

• Desventaja:

• No es posible determinar rápidamente si existe un arco entre dos vértices.


Grafos
• Implementación con Listas Ligadas:

typedef struct Edge

int vertice;

int weight;

struct Edge *sige; /* edge o arco siguiente */

} EDGE;

typedef struct Vertice

int vertice;

struct Edge *sige; /* edge o arco siguiente */

struct Vertice *sigv; /* vertice siguiente */

} VERTICE;
Grafos
typedef struct grafo

int num_vertices;

struct Vertice *head;

} GRAPH;
Grafos
void insert(GRAPH *grafo)

int A,B, weight;

srand(time(0)); /* inicializar el generador de numeros aleatorios */

int no_edges = MAXVERTICES*MAXVERTICES;

for (int i = 1; i <= no_edges; i++)

A = rand_interval( 1, MAXVERTICES);

B = rand_interval( 1, MAXVERTICES);

weight = rand_interval( 1, MAXWEIGHT);

insert_edge(grafo, A, B, weight);

}
Grafos
EDGE * existe_edge(GRAPH *g, int from, int to)

VERTICE *p = g->head;

while (p != NULL)

if (p->vertice == from)

EDGE *edge = get_edge( p->sige, to);

return edge;

p = p -> sigv;

return NULL;

}
Grafos
EDGE * get_edge(EDGE *e, int to)

EDGE *p = e;

while ( p != NULL)

if ( p->vertice == to )

return p;

p = p->sige;

return NULL;

}
Búsqueda en grafos

• ¿Cómo encontrar si existe un Path o camino entre


dos vértices?

• ¿Se puede llegar desde la Unison hasta el Hospital


Infantil?

• ¿Es el mismo camino de vuelta?


Búsqueda en grafos
• Dos tipos de búsquedas:

• Depth-First-Search (DFS)

• (Búsqueda en profundidad)

• Breadth-First-Search (BFS)

• (Búsqueda en anchura)
Depth-First-Search (DFS)
• Algoritmo:

• Sigue un camino tan lejos como puedas llegar.

• Regresa lo menos posible al encontrar un vértice


marcado como “visto” o cuando ya no quedan
más vértices que seguir en el camino.

• DFS usa un “stack” o pila.


Depth-First-Search (DFS)
• "Depth-first-tree" by Alexander Drichel (Wikimedia / Wikipedia)
Depth-First-Search (DFS)
1

2 3

4 5
Depth-First-Search (DFS)
vertice:5 visto
stack:2
1
vertice:2 visto
stack:3
stack:1
stack:4
2 3

vertice:3 visto
stack:1
stack:4
stack:1
stack:4

vertice:1 visto
stack:4
4 5 stack:1
stack:4

vertice: 4 ¡ENCONTRADO!
Depth-First-Search (DFS)
if (encontrado == TRUE)
int encontrado = FALSE;

int vertice; printf("\nSi existe un camino de %d a %d \n", start_vertice,


end_vertice);
NODO *S = NULL; /* creamos el stack */
else
push(&S, start_vertice);
printf("\nNO existe un camino de %d a %d \n", start_vertice,
do { end_vertice);

vertice = pop(&S);

if( vertice == end_vertice) {

encontrado = TRUE;

} else {

mark_it(g, vertice);

push_adjacent_edges(&S, g, vertice);

} while ( (S != NULL) && (encontrado==FALSE) );


DFS
main() crear_grafo()

insert() insert_edge() get_edge()

display() display_edges()

push()

pop()
dfs() mark_it()
push_adjacent
get_vertice()
_vertices()
Breadth - First Search
• http://en.wikipedia.org/wiki/Breadth-first_search

• "Breadth-first-tree" by Alexander Drichel (Wikimedia / Wikipedia)


Breadth - First Search
if (encontrado == TRUE)
int encontrado = FALSE;
printf("\nSi existe un camino de %d a %d \n", start_vertice,
QUEUE *Q = createQueue(); /* creamos la cola */ end_vertice);

push(&S, start_vertice); else

printf("\nNO existe un camino de %d a %d \n", start_vertice,


do {
end_vertice);
vertice = pop(&S);

if( vertice == end_vertice) {

encontrado = TRUE;

} else {

mark_it(g, vertice);

push_adjacent_edges(&S, g, vertice);

} while ( (S != NULL) && (encontrado==FALSE) );


BFS
main() crear_grafo()

insert() insert_edge() get_edge()

display() display_edges()

add()

remove()
dfs()
mark_it()
add_adjacent
_vertices() get_vertice()
• Algunas diapositivas tomadas de:

• https://sites.google.com/site/atulkg/courses/es-103-data-
structure-and-algorithms-2012

• http://www.cse.unr.edu/~bebis/CS302/

• https://www.cs.princeton.edu/~rywang/99f126/

• Algoritmos de DFS y BFS de Wikipedia:

• DFS de: http://en.wikipedia.org/wiki/Depth-first_search

• BFS de: http://en.wikipedia.org/wiki/Breadth-first_search

También podría gustarte