Grafos – Procura (1) • 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. AED (IST/DEEC) 44 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 largura primeiro ( BFS – “Breadth-first-search” ) . AED (IST/DEEC) 45
Grafos – Exploração de labirintos (1) • Teseu 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. AED (IST/DEEC) 46 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. AED (IST/DEEC) 47
Grafos – Exemplo de execução (DFS) AED (IST/DEEC) 48 Grafos – Exemplo de execução (DFS) 0 2 6 4 AED (IST/DEEC) 49
Grafos – Exemplo de execução (DFS) 0 2 6 3 4 5 AED (IST/DEEC) 50 Grafos – Exemplo de execução (DFS) 0 2 6 3 4 5 AED (IST/DEEC) 51
Grafos – Exemplo de execução (DFS) 0 2 6 3 4 5 AED (IST/DEEC) 52 Grafos – Exemplo de execução (DFS) 0 2 6 7 3 4 5 AED (IST/DEEC) 53
Grafos – Exemplo de execução (DFS) 0 2 6 1 7 3 4 5 AED (IST/DEEC) 54 Grafos – Exemplo de execução (DFS) 0 2 6 1 7 3 4 5 AED (IST/DEEC) 55
Grafos – Exemplo de execução (DFS) 0 2 6 1 7 3 4 5 AED (IST/DEEC) 56 Grafos – Exemplo de execução (DFS) 0 2 6 1 7 3 4 5 AED (IST/DEEC) 57
Grafos – Estratégia de Tremaux • Prop: 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 sem regressar à origem; e as que só são visitáveis regressando ao ponto de partida. AED (IST/DEEC) 58 Grafos – DFS • 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. AED (IST/DEEC) 59
Grafos – Implementação de DFS (matriz de adjacências) #define dfsR search Função a ser chamada a void dfsR(Graph G, Edge e) partir de uma função de { procura genérica (“ADT style”) que inicializa o int t, w = e.w; contador cnt a zero e pre[w] = cnt++; todas as entradas da for (t = 0; t < G->V; t++) tabela indexada pelos if (G->adj[w][t] != 0) vértices pre a –1. if (pre[t] == -1) dfsR(G, EDGE(w, t)); } AED (IST/DEEC) 60 Grafos – Descrição da Implementação • A tabela pre está associada com as lâmpadas. Se pre[i] valer –1, significa que a luz está apagada para esse vértice. • Quando se encontra uma aresta para um vértice em que pre não vale –1, um vértice já visitado, essa aresta não é seguida. • Finalmente, a própria estrutura da recursão estabelece o mecanismo equivalente a desenrolar o novelo de fio. • Quando um vértice não possui mais vértices adjacentes com pre igual a –1, a chamada recursiva termina, devolvendo o controlo de execução para o vértice que o antecedeu na recursão. • O retorno da recursão é equivalente a voltar a enrolar o fio. AED (IST/DEEC) 61
Grafos – Implementação de DFS (listas de adjacências) #define dfsR search void dfsR(Graph G, Edge e) { link t; int w = e.w; pre[w] = cnt++; for (t = G->adj[w]; t != NULL; t = t->next) if (pre[t->v] == -1) dfsR(G, EDGE(w, t->v)); } AED (IST/DEEC) 62 Grafos – Comparação • Na implementação por matriz de adjacências, para cada vértice examinam-se todos as arestas que lhe são incidentes por ordem de numeração dos vértices de saída. – Avança sempre pelo primeiro (de índex mais baixo) que não tenha sido visitado e lhe é adjacente. • Na implementação por listas de adjacências, são imediatamente considerados os vértices adjacentes e a ordem de inspecção pode não coincidir com a numeração. – Avança sempre pelo primeiro da lista de adjacências que não tenha sido ainda visitado. AED (IST/DEEC) 63
Grafos – ADT para procura static int cnt, pre[maxV]; GRAPHsearch é uma função ADT para procura genérica em void GRAPHsearch(Graph G) grafos, realizando os seguintes passos: { int v; 1. Encontra um vértice não marcado. cnt = 0; 2. Visita (e marca como visi- for (v = 0; v < G->V; v++) tados) todos os vértices no pre[v] = -1; sub-grafo ligado a que o for (v = 0; v < G->V; v++) primeiro vértice pertence. if (pre[v] == -1) A função de procura não é search(G, EDGE(v, v)); especificada a este nível de } abstracção. AED (IST/DEEC) 64 Grafos – Propriedades da procura • Prop: Uma função de procura em grafos marca cada vértice do grafo se e só se a função de procura que usa marcar cada vértice do sub-grafo ligado que contiver o vértice inicial. – Demonstração trivial por indução no número de sub-grafos ligados máximos. • Prop: A DFS num grafo representado por matriz de adja- cências requer um tempo proporcional a V 2 . – Cada entrada da matriz de adjacências é inspeccionada uma só vez. • Prop: A DFS num grafo representado por listas de adja- cências requer um tempo proporcional a V + E . – Inicialização proporcional a V, V chamadas recursivas e cada elemento das listas de adjacências inspeccionado uma só vez. AED (IST/DEEC) 65
Recommend
More recommend