Algoritmos e Estruturas de Dados
LEE – 2013/14
Teoria de Grafos e Algoritmos em Grafos – 1ª Parte
Grafos - O que é um grafo?
Objecto abstracto
Dois tipos de entidades Nós ou Vértices
Ramos ou Arestas Vértices representam
Cidades, pessoas, máquinas,
números, etc
Arestas representam
Existência de ligações entre nós,
valor da ligação entre nós, distância entre nós, etc
Grafos - Motivação
AED (IST/DEEC) 3
Mapas
caminhos mais curtos; caminhos
mais baratos.
Circuitos Eléctricos
existência de curto-circuitos;
existência de cruzamento entre ligações.
Sequenciamento
tarefas a executar por um
conjunto de recursos sujeitas a restrições de carácter
tecnológico.
Emparelhamento
processamento de imagem
estéreo; atribuição de pessoas a lugares.
Redes de dados
computadores ligados entre si,
enviando e recebendo
mensagens; existência de ligação entre quaisquer nós;
redundância.
Estrutura de Programas grafos gerados por
compiladores representando a estrutura de chamadas;
Grafos – Definições (1)
Definição – Um grafo é um conjunto de vértices e um
conjunto de arestas que ligam pares de vértices distintos (com nunca mais que uma aresta a ligar qualquer par de vértices).
Definição – Dois vértices ligados por uma aresta dizem-se
adjacentes.
Definição – Uma aresta que ligue dois vértices diz-se incidente
Grafos – Definições (2)
AED (IST/DEEC) 5
Definição – O número de arestas incidentes num vértice
diz-se o grau desdiz-se vértice.
Definição – O subconjunto de arestas e vértices a elas
associados diz-se um sub-grafo do grafo original.
Definição – Uma sequência de vértices na qual os vértices
sucessivos estão ligados por arestas do grafo diz-se um caminho.
Grafos – Definições (3)
Definição – Num caminho simples os vértices e arestas são
distintos.
Definição – Um caminho em que todos os vértices e arestas
são distintos, excepto para o primeiro e último que são iguais, diz-se um ciclo.
Definição – Dois caminhos simples dizem-se disjuntos se não
possuírem vértices comuns, excepto possivelmente para os vértices extremos.
Grafos – Definições (4)
AED (IST/DEEC) 7
Definição – Um grafo diz-se ligado se existir um caminho de
cada vértice para todos os outros vértices do grafo.
Definição – Um grafo que não seja ligado é constituído por
componentes ligadas, que se dizem sub-grafos ligados máximos.
Definição – Um grafo ligado acíclico, i.e. sem ciclos, diz-se uma
árvore.
Grafos – Definições (5)
Definição – Um conjunto de árvores diz-se uma floresta.
Definição – A árvore de suporte de um grafo ligado é um
sub-grafo que contém todos os vértices e é uma árvore.
Definição – A floresta de suporte de um grafo é um sub-grafo
Grafos – Propriedades em árvores
AED (IST/DEEC) 9
Um grafo G de V vértices é uma árvore se e só se satisfizer
qualquer das seguintes condições:
G tem V-1 arestas e nenhum ciclo.
G tem V-1 arestas e é ligado.
Existe apenas um caminho simples a unir quaisquer dois vértices.
G é ligado mas retirando uma só aresta faz com que deixe de o ser.
Grafos – Exemplos (1)
Os vértices 6 e 7 são adjacentes. Os vértices 4 e 6 não são adjacentes. O vértice 7 tem grau quatro.
1 4 2 7 6 5 8 3 G
Grafos – Exemplos (2)
AED (IST/DEEC) 11
G’ é um sub-grafo de G, gerado a partir das arestas a cheio. O vértice 5 não pertence a G’.
G é um grafo ligado; G’ não é.
O sub-grafo G’ é constituído por um grafo completo com três
vértices e por uma árvore com quatro vértices
1 4 2 7 6 5 8 3 G’
Grafos – Exemplos (3)
Caminho: 1-2-4-5-7-8 1 4 2 7 6 5 8 3 G Ciclo: 3-4-5-6-7-8-3 1 4 2 7 6 5 8 3 GGrafos – Exemplos (4)
AED (IST/DEEC) 13 G’’: árvore de suporte de G. 1 4 2 7 6 5 8 3 G’’Grafos - Definições e Propriedades (1)
Definição – Um grafo diz-se completo quando existe uma
aresta ligando qualquer par de vértices.
Propriedade – Um grafo com V vértices possui, no máximo,
V(V-1)/2 arestas.
Definição – Um grafo G’ diz-se complemento do grafo G
quando se obtém a partir de um grafo completo com o mesmo número de vértices de G, retirando-lhe todas as arestas de G.
Grafos - Definições e Propriedades (2)
AED (IST/DEEC) 15
Definição – Um grafo que possua um número de arestas
próximo do número máximo diz-se denso.
Definição – Um grafo cujo complemento seja denso diz-se
esparso.
Definição – Densidade de um grafo: 2E/V, em que E é o
número de arestas e V o de vértices.
Definição – A um sub-grafo completo dá-se o nome de clique.
Grafos - Definições e Propriedades (3)
Definição – Um grafo que possua a propriedade de ser
possível dividir os vértices em dois conjuntos tais que todas as arestas apenas ligam vértices de um conjunto a vértices do outro conjunto diz-se bipartido.
Definição – Quando existe um sentido atribuído às arestas, os
grafos dizem-se direccionados, dirigidos ou digrafos.
Definição – O primeiro vértice de uma aresta direccionada
Grafos - Definições e Propriedades (4)
AED (IST/DEEC) 17
Propriedade – Apenas os vértices destino são adjacentes dos
vértices fonte.
Definição – Um ciclo direccionado num digrafo é um ciclo em
que todos os pares de vértices adjacentes surgem pela ordem especificada pelas arestas.
Definição – Um digrafo sem ciclos direccionados diz-se grafo
direccionado acíclico, ou DAG (Directed Acyclic Graph).
Grafos - Definições e Propriedades (5)
Definição – Quando se atribuem pesos às arestas,
representando custo, distância, etc., diz-se que o grafo é ponderado.
Também é possível atribuir pesos aos próprios vértices, ou a pares
vértice/aresta.
Grafos - Interface ADT para Grafos (1)
AED (IST/DEEC) 19
Os algoritmos para processamento de grafos serão
desenvolvidos no contexto de uma ADT que define as tarefas de interesse.
A nossa primeira interface elementar é tal que:
O número de vértices e arestas são especificados por inteiros; Uma aresta é definida por um par de inteiros, designando os
vértices que une;
O número de vértices é limitado superiormente.
Esta interface irá sendo alargada à medida das necessidades.
Grafos - Interface ADT para Grafos (2)
typedef struct edge Edge; Edge *EDGE(int, int);
typedef struct graph Graph; Graph *GRAPHinit(int);
void GRAPHinsertE(Graph *G, Edge*); void GRAPHremoveE(Graph *G, Edge*); int GRAPHedges(Edge a[], Graph *G); Graph *GRAPHcopy(Graph G*);
void GRAPHdestroy(Graph G*);
Graphinit cria grafo com o
número final de vértices, sem arestas.
GraphinsertE insere uma
aresta, caso não exista.
GraphremoveE retira uma
aresta, caso exista.
Graphedges conta o número
de arestas.
Graphcopy cria uma segunda
cópia do grafo.
Graphdestroy faz o inverso de Graphinit.
Grafos - Matriz de Adjacências (1)
AED (IST/DEEC) 22
Matriz de Adjacências
Matriz (VxV) de valores booleanos;
A entrada correspondente à linha v e coluna w é 1 se existir uma aresta
ligando estes dois vértices;
A mesma entrada vale 0 caso contrário;
A matriz é simétrica, excepto para digrafos, em que poderá não sê-lo.
Grafos - Matriz de Adjacências (2)
1 4 2 7 6 5 8 3 G Grafo 1 2 3 4 5 6 7 8 1 1 1 0 1 0 0 0 0 2 1 1 0 1 0 0 0 0 3 0 0 1 1 0 0 1 1 4 1 1 1 1 1 0 0 0 5 0 0 0 1 1 1 1 0 6 0 0 0 0 1 1 1 0 7 0 0 1 0 1 1 1 1 8 0 0 1 0 0 0 1 1 Matriz
Grafos - Implementação de ADT (1)
AED (IST/DEEC) 24
#include <stdlib.h> #include “GRAPH.h”
struct graph {int V; int E; int **adj;}; struct edge {int v; int w;};
Graph *GRAPHinit(int V) {
Graph *G = (Graph*) malloc(sizeof(struct graph)); G->V = V; G->E = 0;
G->adj = MATRIXint(V, V, 0); return G;
}
void GRAPHinsertE(Graph *G, Edge *e){ int v = e->v, w = e->w;
if (G->adj[v][w] == 0) G->E++; G->adj[v][w] = 1;
G->adj[w][v] = 1; }
Grafos - Implementação de ADT (2)
void GRAPHremoveE(Graph *G, Edge *e) {
int v = e->v, w = e->w;
if (G->adj[v][w] == 1) G->E--; G->adj[v][w] = 0;
G->adj[w][v] = 0; }
int GRAPHedges(Edge a[], Graph G*) { int v, w, E = 0; for (v = 0; v < G->V; v++) for (w = v+1; w < G->V; w++) if (G->adj[v][w] == 1) a[E++] = EDGE(v, w); return E;
Grafos – Síntese da Aula 1
AED (IST/DEEC) 26 Introdução Definição de grafo Motivação aplicacional Definições e notação Propriedades elementares em grafos Exemplos
Definições e propriedades
Grafos completos, complemento de um grafo, densidade, cliques, grafos
bipartidos, grafos direccionados, ciclos em grafos direccionados, grafos ponderados, redes.
Estrutura abstracta de dados para grafos
Interface elementar
Representação de um grafo
Matriz de adjacências
Grafos - Listas de Adjacências (1)
Listas de Adjacências
Cada vértice possui uma lista ligada;
Os elementos constituintes da lista de um vértice são os seus vértices
adjacentes;
Em grafos simples, se os vértices v e w são adjacentes, então w pertence
Tabela com V listas* de arestas
Grafos - Lista de Adjacências (2)
AED (IST/DEEC) 28 1 4 2 7 6 5 8 3 G
Grafo Lista de Adjacências
4 1 2 4 1 2 3 8 7 8 4 3 7 2 1 3 4 5 6 4 5 7 5 6 7 6 3 5 7 8
* V ponteiros para lista
Grafos - Implementação de ADT (1)
#include <stdlib.h> #include “GRAPH.h”
typedef struct node link;
struct node {int v; link *next;};
struct graph{int V; int E; link **adj;}; link NEW(int v, link *next)
{
link *x = (link *) malloc(sizeof(struct node)); x->v = v;
x->next = next; return x;
Grafos - Implementação de ADT (2)
AED (IST/DEEC) 30 Graph GRAPHinit(int V) { int v;Graph *G = (Graph*) malloc(sizeof(struct graph)); G->V = V;
G->E = 0;
G->adj = (link **) malloc(V * sizeof(link*)); for (v = 0; v < V; v++)
G->adj[v] = NULL; return G;
}
void GRAPHinsertE(Graph *G, Edge *e) {
int v = e->v, w = e->w;
G->adj[v] = NEW(w, G->adj[v]); G->adj[w] = NEW(v, G->adj[w]); G->E++;
}
Grafos - Implementação de ADT (3)
void GRAPHremoveE(Graph *G, Edge *e) {
/* Fica como exercício */
}
int GRAPHedges(Edge a[], Graph *G) {
int v, E = 0; link t;
for (v = 0; v < G->V; v++)
for (t = G->adj[v]; t != NULL; t = t->next) if (v < t->v )
a[E++] = EDGE(v, t->v); return E;
Grafos - Vantagens das M. de Adj.
AED (IST/DEEC) 32
Representação de eleição quando há espaço disponível;
os grafos são densos;
os algoritmos requerem mais que V2 operações.
Adição e remoção de arestas é feita de forma eficiente;
É fácil evitar a existência de arestas paralelas;
É fácil determinar se dois vértices estão ou não ligados.
Grafos - Inconvenientes das M. de Adj.
Grafos esparsos de grande dimensão requerem espaço de
memória proporcional a V2;
Neste casos, a simples inicialização do grafo (proporcional a
V2) pode ser dominante na execução global do algoritmo;
Pode nem sequer existir memória suficiente para armazenar a
Grafos - Vantagens das L. de Adj.
AED (IST/DEEC) 34
Inicialização é proporcional a V.
Utiliza sempre espaço proporcional a V+E adequado para grafos esparsos.
algoritmos que assentem na análise de arestas em grafos esparsos.
Adição de arestas é feita de forma eficiente.
Grafos - Inconvenientes das L. de Adj.
Arestas paralelas e adjacência entre vértices
requer que se pesquise as listas de adjacências, o que pode levar um
tempo proporcional a V.
Remoção de arestas
pode levar um tempo proporcional a V (este problema pode ser
contornado).
Não aconselhável para
grafos de grande dimensão que não podem ter arestas paralelas; grande utilização de remoção de arestas.
Grafos - Variantes e Extensões (1)
AED (IST/DEEC) 36
Outros tipos de grafos Digrafos
ambas facilmente extensíveis; arestas representadas só uma vez; Grafos ponderados e redes
M. de Adj. preenchida com pesos;
L. De Adj. com campos extra para representação dos pesos.
Grafos - Variantes e Extensões (2)
Alteração da estrutura de dados
Tipo “EDGE” contendo informação adicional, para além dos vértices que
liga.
Vectores indexados pelos vértices
Manutenção da informação do grau do vértice. Vector de arestas
Grafos - Representações alternativas
AED (IST/DEEC) 38
Três mecanismos básicos de representação de grafos Vector de arestas;
Matriz de adjacências; Listas de adjacências.
Produzem diferentes desempenhos ao nível das operações de
manipulação.
Escolha deverá depender do problema a resolver.
Grafos – Desempenho Relativo
V. de Arestas M. de Adj. L. de Adj.
Espaço E V2 V+E Inicialização 1 V2 V Cópia E V2 E Destruição 1 V E Inserir aresta 1 1 1 Encontrar aresta E 1 V Remover aresta E 1 V Vértice isolado? E V 1
Grafos - Encontrar e remover arestas (1)
AED (IST/DEEC) 40
Eficientes em representações por matriz de adjacências. Como torná-las eficientes para as outras representações?
Atribuir um símbolo inteiro a cada aresta Aresta v-w fica com o símbolo v*V+w.
Por exemplo, fazer uso de tabelas de dispersão (“hash-tables”)
Quando uma aresta é inserida, é fácil testar se o símbolo já foi
usado.
Grafos - Encontrar e remover arestas (2)
Remoção em digrafos
ponteiro na tabela de dispersão para a sua representação na lista de
adjacências;
requer listas duplamente ligadas.
Remoção em grafos simples
colocação de ambos os ponteiros na tabela de dispersão; ou ponteiro entre os vértices.
Grafos – Procura (1)
AED (IST/DEEC) 43
Algumas propriedades simples em grafos são fáceis de
determinar, independentemente da ordem pela qual se examinam as arestas.
Ex: grau de todos os vértices.
Outras propriedades estão associadas a caminhos, pelo que se
torna necessário identificá-las através de pesquisa feita de vértice em vértice ao longo das arestas.
A maioria dos algoritmos em grafos que consideraremos usam
este modelo abstracto básico.
Torna-se então necessário analisar o essencial dos algoritmos
de procura em grafos e suas propriedades estruturais.
Grafos – Procura (2)
Procurar em grafos é equivalente a percorrer labirintos Necessário marcar pontos já visitados
Ser-se capaz de recuar, num caminho efectuado, até ao ponto de partida. Os vários algoritmos de procura em grafos mais não fazem
que executar uma determinada estratégia de procura em labirintos.
Procura em profundidade primeiro (DFS – “Depth-first-search”). Admite duas implementações: recursiva e com uso de pilha explícita. Substituindo a pilha por uma fila FIFO, transforma-se em procura em
Grafos – Exploração de labirintos (1)
AED (IST/DEEC) 45
Teseu, Ariadne e o seu pequeno problema com o Minotauro Desenrolar um rolo de fio para poder voltar ao princípio
Marcar os lugares já visitados para evitar repetição. Nós e os grafos
Existem lâmpadas, inicialmente apagadas, em cada encruzilhada – vértice. Cada corredor – aresta – possui um par de portas, inicialmente fechadas,
no início e no fim deste.
As portas têm janelas que nos permitem ver se a porta do lado oposto
está ou não fechada e se a luz da encruzilhada correspondente está ou não acesa.
O objectivo é regressar à encruzilhada inicial tendo aberto todas as
portas e acendido todas as luzes.
Necessitamos um conjunto de regras que garanta que tal acontece.
Grafos – Exploração de labirintos (2)
Estratégia – Exploração de Tremaux
1. Abrir uma qualquer porta que esteja fechada e dê acesso a uma saída da presente encruzilhada (deixá-la aberta). Se todas as portas estiverem abertas, saltar para 3.
2. Se a partir da porta que foi aberta for visível que a encruzilhada em que o corredor termina foi acesa, abrir outra porta (passo 1). Caso contrário (a encruzilhada está às escuras), seguir o corredor, desenrolando o fio, até essa encruzilhada, acender a luz e voltar ao passo 1.
3. Se todas as portas estão abertas na presente encruzilhada, verificar se é a primeira visitada. Se sim, parar. Se não, usar o fio para recuar até à última encruzilhada visitada e voltar ao passo 1.
Grafos – Exemplo de execução (DFS)
AED (IST/DEEC) 47 2 6 4 3 5 7 1 0 Acende a luz no primeirovértice e abre a primeira porta (do vértice 0 para o vértice 2) e segue em frente abrindo sempre a única porta existente (até ao vértice 4).
Escolhe uma das portas e continua seguindo em frente enquanto não houver escolha. No vértice 5 todas as portas conduzem a corredores que dão acesso a vértices de luz acesa.
Recua até ao último vértice que ainda possui portas por abrir.
Neste vértice (4), a única porta que dá acesso a pontos não visitados leva-nos para o vértice 7. Chegados ao vértice 1, não há mais portas por abrir, pelo que inicia o processo de recuo. No vértice 4 já estão todas as portas abertas, pelo que tem que continuar a recuar.
No vértice 0 ainda há portas por abrir. No vértice 0 já não há portas por abrir.
Grafos – Estratégia de Tremaux
Propriedade – Quando se usa a estratégia de exploração de
labirintos de Tremaux abrem-se todas as portas, acendem-se todas as luzes e termina-se no local de partida.
Demonstração (esboço):
Prova-se por indução, mostrando primeiro ser verdade para um labirinto
com apenas uma encruzilhada e nenhum corredor – basta acender a única luz.
Para um labirinto com mais que uma encruzilhada assume-se ser verdade
para todos os labirintos menores com menos encruzilhadas.
Bastará mostrar que se visitam todas as intersecções, dado que se abrem
todas as portas de cada uma delas.
Considere-se o primeiro corredor tomado.
O grafo fica dividido em dois sub-grafos: as intersecções que se visitam
Grafos – DFS
AED (IST/DEEC) 59
Notar que a estratégia de procura de Tremaux, mais não é que
procura em profundidade primeiro.
O algoritmo procede sempre abrindo uma porta e
afastando-se da origem, até que chega a um ponto em que não pode abrir mais portas, tendo então que recuar até ao último ponto onde deixou, pelo menos, uma porta por abrir.
Se ao recuar nunca encontrar portas por abrir, acabará
regressando ao ponto de partida, dado que o fio que desenrolou no caminho descendente, lhe permite esse regresso.
Grafos – Síntese da Aula 2
Representação de um grafo
Listas de adjacência; Implementações da estrutura abstracta de dados Comparação das representações alternativas
Vantagens e inconvenientes das matrizes de adjacência; Vantagens e
inconvenientes das listas de adjacência
Variantes e extensões
Grafos direccionados, ponderados e redes; Outras representações Comparação das representações alternativas
Memória e tempo de execução Procura em grafos