Você está na página 1de 48

Disciplina: Técnicas de programação

Curso: Engenharia da computação

Aula 14 – Buscas em grafos


rafael.joao@ifsp.edu.br
P R O F. R A FA E L S TO F FA L E T T E J O Ã O Atendimento: sala ADM113
Qua 13h00 às 14h00
DATA : 2 2 / 0 5 / 2 0 1 9 Qui 18h30 às 20h30

Campus Birigui
Teoria dos grafos
Formalmente:
G = {V, A}, onde V é o conjto. de vértices e A as arestas;
V = {u,v}, ondem u e v são vértices
Se e = uv é uma aresta de um grafo G então dizemos que u e v são adjacentes em G e que e liga
u e v.

v
A aresta é incidente aos vértices

w u

22/05/2019 2
Teoria dos grafos
G = {V,A}
V= {u, v, w, x, y, z} e
A= {uv, uw,wx, xy, xz}

v
O número de vértices será simbolizado por |V | ou pela letra n.
◦ Também chamado de ordem do grafo.
y x w u

O número de arestas será simbolizado por |A| ou pela letra m.


◦ A soma das arestas descreve o tamanho do grafo.
z
No exemplo n = 6 e m = 5.

22/05/2019 3
Representação por matrizes
O grafo G={V,A}, onde:
◦ V = {a,b,c,d}
◦ A ={(a,b),(a,c),(a,d), (b,c), (c,d)}

Pode ser reescrito por sua matriz de adjacência:

Gerando a matriz Ma:

Forma mais fácil de implementar um grafo

22/05/2019 4
Alguns conceitos
O que é um grafo completo?

O que é um ciclo?

O que é um laço?

O que é o grau de um vértice?

O que quer dizer um grafo 4-regular?

22/05/2019 5
TAD grafo
Um grafo é composto pelos itens:

◦ Conjunto de arestas; Quantas?


◦ Conjunto de vértices; Quantos?

Se a matriz de adjacências é uma forma simples de


implementar um grafo, como fazer?

22/05/2019 6
TAD grafo
Um grafo é composto pelos itens: typedef struct grafo{
int qtdVertices;
◦ Conjunto de arestas; Quantas?
int qtdArestas;
◦ Conjunto de vértices; Quantos?
int matrizAdj[MAX][MAX];
} tipo_grafo;
Se a matriz de adjacências é uma forma simples de
implementar um grafo, como fazer?

0 0 0
matrizAdj[3][3]: 0 0 0
0 0 0

22/05/2019 7
TAD grafo
Um grafo é composto pelos itens:

◦ Conjunto de arestas; Quantas?


◦ Conjunto de vértices; Quantos?

Se a matriz de adjacências é uma forma simples de


implementar um grafo, como fazer?

0 0 0
INICIALIZA-SE ATRIBUÍNDO ZEROS PARA TODAS AS ARESTAS 0 0 0
0 0 0

22/05/2019 8
TAD grafo
Inserir uma nova aresta entre os vértices u e v:

matrizAdj[u][v] = 1;

v
0 0 0
insereAresta(G, 1, 2) 0 0 1
w u 0 0 0

22/05/2019 9
TAD grafo
Remover uma aresta entre os vértices u e v:

matrizAdj[u][v] = 0;

v
0 0 0
removeAresta(G, 1, 2) 0 0 0
w u 0 0 0

22/05/2019 10
TAD grafo
E se não sabemos a quantidade máxima de vértices de
um grafo?

Implementação dinâmica com listas de adjacência:

Uma lista encadeada de vértices, onde cada vértice tem


uma lista de adjacência
para cada vértice do grafo, há uma lista de todos os
outros vértices com os quais ele tem uma aresta

22/05/2019 11
Existência de caminhos
- Um ciclo é um grafo conexo regular de grau 2.

- Caminho é o grafo resultante do percurso de um vértice (início) até outro vértice (destino)
Caminho de 8B até 7A:
◦ C1: {(8B,6A),(6A,7A)}
◦ C2: {(8B,7B),(7B,6A), (6A,7A)}
◦ C3: {(8B,6B),(6B,7A)}
◦ C4: {(8B,8A), (8A,7B), (7B,6A), (6A,7A)}
◦ ...

22/05/2019 12
Existência de caminhos
Como implementar esse problema?

Ciclo:
◦ Partir de um vértice u e retornar ao vértice u

Caminho:
◦ Partir de um vértice u e encontrar um vértice v

22/05/2019 13
Existência de caminhos
Um vértice u em um grafo está ao alcance de (ou é acessível a partir de) um vértice v se existe
um caminho de u até v

6A está ao alcance de 8A ? Por quê?

22/05/2019 14
Existência de caminhos
Marcar cada vértice
visitado e continuar
buscando enquanto
houver caminho.

22/05/2019 15
Busca em grafos
Um algoritmo de busca (ou de varredura) é um algoritmo que visita todos os vértices de
um grafo andando pelas arestas de um vértice a outro.

Há muitas maneiras de fazer uma tal busca.

Cada algoritmo de busca é caracterizado pela ordem em que os vértices são visitados.

22/05/2019 16
Busca em profundidade (DFS)
depth-first search

É próximo ao algoritmo de busca da existência de caminhos;


Objetivo: visitar todos os vértices e numerá-los na ordem em que são descobertos.

Relacionada a teorias como backtracking e pré-ordem;

22/05/2019 17
Busca em profundidade (DFS)
Origem: v

A partir de v, encontrando um primeiro vértice adjacente (t) chama-se a função recursivamente


tentando encontrar TODOS os vértices a partir de t.

O vetor “listaVisitados” serve para garantir uma só visita a cada vértice.

22/05/2019 18
Busca em profundidade (DFS)
A partir do vértice 0;
Visitado: 1 0 0 0 0
3

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 19
Busca em profundidade (DFS)
Contador de visita: 1
A partir do vértice 0;
Visitado: 1 0 0 0 0
3

Adjacentes ao vértice 0: {1}

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 20
Busca em profundidade (DFS)
Contador de visita: 2
A partir do vértice 1;
Visitado: 1 2 0 0 0
3

Adjacentes ao vértice 1: {2,3}

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 21
Busca em profundidade (DFS)
Contador de visita: 3
A partir do vértice 2;
Visitado: 1 2 3 0 0
3

Adjacentes ao vértice 2: {4}

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 22
Busca em profundidade (DFS)
Contador de visita: 4
A partir do vértice 2;
Visitado: 1 2 3 0 4
3

Adjacentes ao vértice 4: {1}

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 23
Busca em profundidade (DFS)
Contador de visita: 3
A partir do vértice 2;
Visitado: 1 2 3 0 4
3

Adjacentes ao vértice 4: {1}. JÁ FOI VISITADO

0 1 0 0 0 0 1 4
Como não há outro adjacente de 4, a recursão volta:
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 24
Busca em profundidade (DFS)
Contador de visita: 3
A partir do vértice 2;
Visitado: 1 2 3 0 4
3

Adjacentes ao vértice 2: {4}

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 25
Busca em profundidade (DFS)
Contador de visita: 3
A partir do vértice 2;
Visitado: 1 2 3 0 4
3

Adjacentes ao vértice 2: {4} JÁ FOI VISITADO

0 1 0 0 0 0 1 4
Como não há outro adjacente de 2, a recursão volta:
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 26
Busca em profundidade (DFS)
Contador de visita: 2
A partir do vértice 1;
Visitado: 1 2 3 0 4
3

Adjacentes ao vértice 1: {2,3}


2 JÁ FOI VISITADO
0 1 0 0 0 0 1 4
3 AINDA NÃO
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 27
Busca em profundidade (DFS)
Contador de visita: 3
A partir do vértice 1;
Visitado: 1 2 3 3 4
3

Adjacentes ao vértice 3: {0,4}


0 JÁ FOI VISITADO
0 1 0 0 0 0 1 4
4 JÁ FOI VISITADO
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 28
Busca em profundidade (DFS)
Contador de visita: 3
A partir do vértice 1;
Visitado: 1 2 3 3 4
3

Adjacentes ao vértice 3: {0,4}


0 JÁ FOI VISITADO
0 1 0 0 0 0 1 4
4 JÁ FOI VISITADO
0 0 1 1 0
0 0 0 0 1
NÃO HÁ MAIS VÉRTICES PARA VISITAR à FIM. 1 0 0 0 1 2
0 1 0 0 0

22/05/2019 29
Busca em profundidade (DFS)
Como implementar?

Deve-se manter um contador que descreve a ”profundidade” da busca;


Selecionar o vértice inicial e:
◦ MARCAR O VÉRTICE ATUAL;
◦ VISITAR OS ADJACENTES;

Repetir recursivamente garante que ao encontrar um adjacente ele visite o adjacente e depois
olhe os demais; PROFUNDIDADE

22/05/2019 30
Busca em largura (BFS)
Breadth-First Search

Os vértices descobertos mais antigos são “analisados” primeiro Escolhe-se as arestas que
partem destes vértices
Explorar todos os vértices vizinhos e repetir a busca para todos os vizinhos;

Lembra a busca em profundidade

22/05/2019 31
Busca em largura (BFS)
Marcar todos os vértices como não visitados:
Utiliza-se uma fila como auxiliar para marcar a ordem das visitas;
◦ Nos lembra o percurso em nível das árvores.

Verificar TODOS os vizinhos do vértice atual


Se não foi visitado:
Colocar ele na fila e marca como visitado

O algoritmo enumera os vértices, em sequência, na ordem em que eles são descobertos

22/05/2019 32
Busca em largura(BFS)
Contador: 1
Vértice atual:
Visitados: 1 0 0 0 0
3

Fila auxiliar 0

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 33
Busca em largura(BFS)
Contador: 1
Vértice atual: 0
Visitados: 1 0 0 0 0
3

Fila auxiliar 0

0 1 0 0 0 0 1 4
Processa a fila: 0 0 1 1 0
Remove o elemento mais antigo: 0 0 0 0 0 1
1 0 0 0 1 2
Por na fila os adjacentes do vértice processado
0 1 0 0 0

22/05/2019 34
Busca em largura(BFS)
Contador: 2
Vértice atual: 0
Visitados: 1 2 0 0 0
3

Fila auxiliar 1

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 35
Busca em largura(BFS)
Contador: 2
Vértice atual: 1
Visitados: 1 2 0 0 0
3

Fila auxiliar 1

0 1 0 0 0 0 1 4
Processa a fila: 0 0 1 1 0
Remove o elemento mais antigo: 1 0 0 0 0 1
1 0 0 0 1 2
Por na fila os adjacentes do vértice processado
0 1 0 0 0

22/05/2019 36
Busca em largura(BFS)
Contador: 3
Vértice atual: 1
Visitados: 1 2 3 3 0
3

Fila auxiliar 3 2

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 37
Busca em largura(BFS)
Contador: 3
Vértice atual: 1
Visitados: 1 2 3 3 0
3

Fila auxiliar 3 2

0 1 0 0 0 0 1 4
Processa a fila: 0 0 1 1 0
Remove o elemento mais antigo: 2 0 0 0 0 1
1 0 0 0 1 2
Por na fila os adjacentes do vértice processado
0 1 0 0 0

22/05/2019 38
Busca em largura(BFS)
Contador: 4
Vértice atual: 2
Visitados: 1 2 3 3 4
3

Fila auxiliar 4 3

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 39
Busca em largura(BFS)
Contador: 4
Vértice atual: 2
Visitados: 1 2 3 3 4
3

Fila auxiliar 4 3

0 1 0 0 0 0 1 4
Processa a fila: 0 0 1 1 0
Remove o elemento mais antigo: 3 0 0 0 0 1
1 0 0 0 1 2
Por na fila os adjacentes do vértice processado
0 1 0 0 0

22/05/2019 40
Busca em largura(BFS)
Contador: 4
Vértice atual: 3
Visitados: 1 2 3 3 4
3

Fila auxiliar 0 4

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 41
Busca em largura(BFS)
Contador: 4
Vértice atual: 3
Visitados: 1 2 3 3 4
3

Fila auxiliar X0 4
0 já foi processado: não entra na fila
0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 42
Busca em largura(BFS)
Contador: 4
Vértice atual: 3
Visitados: 1 2 3 3 4
3

Fila auxiliar 4

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 43
Busca em largura(BFS)
Contador: 4
Vértice atual: 3
Visitados: 1 2 3 3 4
3

Fila auxiliar 4

0 1 0 0 0 0 1 4
Processa a fila: 0 0 1 1 0
Remove o elemento mais antigo: 4 0 0 0 0 1
1 0 0 0 1 2
Por na fila os adjacentes do vértice processado
0 1 0 0 0

22/05/2019 44
Busca em largura(BFS)
Contador: 4
Vértice atual: 4
Visitados: 1 2 3 3 4
3

Fila auxiliar

0 1 0 0 0 0 1 4
0 0 1 1 0
0 0 0 0 1
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 45
Busca em largura(BFS)
Contador: 4
Vértice atual: 4
Visitados: 1 2 3 3 4
3

Fila auxiliar

0 1 0 0 0 0 1 4
FILA VAZIA: Todos vértices já visitados 0 0 1 1 0
0 0 0 0 1
FIM.
1 0 0 0 1 2
0 1 0 0 0

22/05/2019 46
Caminho Hamiltoniano
Um caminho hamiltoniano é um caminho que permite passar por todos os vértices de
um grafo G, não repetindo nenhum à caminho entre u e v que passa por TODOS os vértices;

Caso esse caminho seja possível descrever um ciclo, este é denominado ciclo hamiltoniano;

Um grafo que possua tal circuito é chamado de grafo hamiltoniano.

22/05/2019 47
Prática checkpoint (vale: 4)
1. Implementar uma função que verifica o grau de um dado vértice;

2. Implementar uma função que verifica se um grafo é regular. Se sim informar o grau;

3. Implementar uma função que verifica se um grafo é completo;

4. Imprimir o grafo em formato de parênteses;

5. Implementar uma função que verifica a existência de um CAMINHO, por meio da busca em largura;

6. Implementar uma função que verifica a existência de CICLOS em um grafo;

7. Implementar uma função que verifica a existência de um CAMINHO HAMILTONIANO em um grafo;

22/05/2019 48

Você também pode gostar