Unidade23 Grafos Estrutura Handout
Unidade23 Grafos Estrutura Handout
Unidade23 Grafos Estrutura Handout
Grafos
Rafael C. S. Schouery
[email protected]
Carlos Beto
Daniel Ana
Eduardo Felipe
2
Grafos
Um Grafo é um conjunto de objetos ligados entre si
• Chamamos esses objetos de vértices
– Ex: pessoas em uma rede social
• Chamamos as conexões entre os objetos de arestas
– Ex: relação de amizade na rede social
3 0
4 5
3 0
4 5
5
Matriz de Adjacências
Vamos representar um grafo por uma matriz de adjacências
• Se o grafo tem n vértices
• Os vértices serão numerado de 0 a n − 1
• A matriz de adjacências é n × n
• adjacencia[u][v] = 1 - u e v são vizinhos
• adjacencia[u][v] = 0 - u e v não são vizinhos
0 1 2 3 4 5
2 1
0 0 1 0 0 1 0
1 1 0 1 0 1 0
3 0
2 0 1 0 1 0 1
3 0 0 1 0 0 1
4 1 1 0 0 0 1
4 5 5 0 0 1 1 1 0
6
TAD Grafo
7
Inicialização e Destruição
1 p_grafo criar_grafo(int n) {
2 int i, j; 0 0 0 0 0 0
1 void destroi_grafo(p_grafo g) {
2 int i;
3 for (i = 0; i < g->n; i++)
4 free(g->adj[i]);
5 free(g->adj);
6 free(g);
7 }
8
Manipulando arestas
9
Lendo e Imprimindo um Grafo
1 p_grafo le_grafo () {
2 int n, m, i, u, v;
3 p_grafo g;
4 scanf("%d %d", &n, &m);
5 g = criar_grafo(n);
6 for (i = 0; i < m; i++) {
7 scanf("%d %d", &u, &v);
8 insere_aresta(g, u, v);
9 }
10 return g;
11 }
1 void imprime_arestas(p_grafo g) {
2 int u, v;
3 for (u = 0; u < g->n; u++)
4 for (v = u+1; v < g->n; v++)
5 if (g->adj[u][v])
6 printf("{%d,%d}\n", u, v);
7 }
10
Quem é o mais popular?
O grau de um vértice é o seu número de vizinhos
2 1
3 0
4 5
11
Quem é o mais popular?
1 int mais_popular(p_grafo g) {
2 int u, max , grau_max , grau_atual;
3 max = 0;
4 grau_max = grau(g, 0);
5 for (u = 1; u < g->n; u++) {
6 grau_atual = grau(g, u);
7 if (grau_atual > grau_max) {
8 grau_max = grau_atual;
9 max = u;
10 }
11 }
12 return max;
13 }
12
Indicando amigos
Carlos Beto
Daniel Ana
Eduardo Felipe
13
Indicando amigos
14
Seguindo e sendo seguido
Carlos Beto
Daniel Ana
Eduardo Felipe
15
Grafos dirigidos
Um Grafo dirigido (ou Digrafo)
• Tem um conjunto de vértices
• Conectados através de um conjunto de arcos
– arestas dirigidas, indicando início e fim
2 1
3 0
4 5
3 0
4 5
2 1
3 0
4 5
0
1 9
2 8
3 7
4 6
5
( )
n n(n − 1)
Até = = O(n2 ) arestas
2 2
19
Grafos esparsos
Um grafo tem no máximo n(n − 1)/2 arestas, mas pode ter bem
menos...
20
Grafos esparsos
Dizemos que um grafo é esparso se ele tem “poucas” arestas
• Bem menos do que n(n − 1)/2
Exemplos:
• Facebook:
– Cada usuário tem no máximo 5000 amigos
– O máximo de arestas é 5,5 · 1012
– Bem menos do que 2,4 · 1018
• Grafos cujos vértices têm o mesmo grau d (constante)
– O número de arestas é dn/2 = O(n)
• Grafos com O(n lg n) arestas
21
Listas de Adjacência
Representando um grafo por Listas de Adjacência:
• Temos uma lista ligada para cada vértice
• A lista armazena quais são os vizinhos do vértice
v[0] 1 4
2 1
v[1] 0 2 4
v[2] 1 3 5
3 0
v[3] 2 5
4 5 v[4] 0 1 5
v[5] 2 3 4
22
TAD Grafo com Listas de Adjacência
1 typedef struct no *p_no;
2
3 struct no {
4 int v;
5 p_no prox;
6 };
7
8 typedef struct grafo *p_grafo;
9
10 struct grafo {
11 p_no *adjacencia;
12 int n;
13 };
14
15 p_grafo criar_grafo(int n);
16
17 void destroi_grafo(p_grafo g);
18
19 void insere_aresta(p_grafo g, int u, int v);
20
21 void remove_aresta(p_grafo g, int u, int v);
22
23 int tem_aresta(p_grafo g, int u, int v);
24
25 void imprime_arestas(p_grafo g);
23
Inicialização e Destruição
1 p_grafo criar_grafo(int n) {
2 int i;
3 p_grafo g = malloc(sizeof(struct grafo));
4 g->n = n;
5 g->adjacencia = malloc(n * sizeof(p_no));
6 for (i = 0; i < n; i++)
7 g->adjacencia[i] = NULL;
8 return g;
9 }
1 void destroi_grafo(p_grafo g) {
2 int i;
3 for (i = 0; i < g->n; i++)
4 libera_lista(g->adjacencia[i]);
5 free(g->adjacencia);
6 free(g);
7 } 24
Inserindo uma aresta
25
Removendo uma aresta
1 p_no remove_da_lista(p_no lista , int v) {
2 p_no proximo;
3 if (lista == NULL)
4 return NULL;
5 else if (lista ->v == v) {
6 proximo = lista ->prox;
7 free(lista);
8 return proximo;
9 } else {
10 lista ->prox = remove_da_lista(lista ->prox , v);
11 return lista;
12 }
13 }
26
Verificando se tem uma aresta e imprimindo
1 void imprime_arestas(p_grafo g) {
2 int u;
3 p_no t;
4 for (u = 0; u < g->n; u++)
5 for (t = g->adjacencia[u]; t != NULL; t = t->prox)
6 printf("{%d,%d}\n", u, t->v);
7 }
27
O Problema das Pontes de Königsberg
Königsberg (hoje Kaliningrado, Rússia) tinha 7 pontes
• Acreditava-se que era possível passear por toda a cidade
• Atravessando cada ponte exatamente uma vez
A D
A D
Tempo:
Operação Matriz Listas
Inserir O(1) O(1)
Remover O(1) O(d(v))
Aresta existe? O(1) O(d(v))
Percorrer vizinhança O(|V |) O(d(v))
Qual usar?
• Depende das operações usadas e se o grafo é esparso
30
Importância dos Grafos
Grafos são amplamente usados na Computação e na Matemática
para a modelagem de problemas:
• Redes Sociais: grafos são a forma de representar uma relação
entre duas pessoas
• Mapas: podemos ver o mapa de uma cidade como um grafo e
achar o menor caminho entre dois pontos
• Páginas na Internet: links são arcos de uma página para a
outra - podemos querer ver qual é a página mais popular
• Redes de Computadores: a topologia de uma rede de
computadores é um grafo
• Circuitos Eletrônicos: podemos criar algoritmos para ver se há
curto-circuito por exemplo
• etc...
31