• Nenhum resultado encontrado

Estrutura de dados e algoritmos

No documento Similaridade de grafos via hashing (páginas 32-36)

1.4 Organiza¸c˜ao dessa disserta¸c˜ao

2.1.4 Estrutura de dados e algoritmos

A seguir s˜ao apresentadas duas estruturas de dados b´asicas para representa¸c˜ao de gra- fos em geral: (1) matriz de adjacˆencia e (2) listas de adjacˆencia. O emprego dessas

2.1. Princ´ıpios b´asicos da Teoria de Grafos 11

estruturas interfere diretamente no tempo de processamento dos m´etodos de compara- ¸c˜ao entre grafos. Posteriormente, algoritmos para pesquisa de v´ertices e computa¸c˜ao de caminhos m´ınimos no grafo s˜ao descritos e analisados. Esses algoritmos s˜ao extre-

mamente ´uteis e s˜ao utilizados por diversos m´etodos para c´alculo de similaridade entre

estruturas. 2.1.4.1 Estruturas

0 1 0 0 1

1 0 1 1 0

0

1

0

1

0

0

1

1

0

1

1

0

0

1

0

(a) Matriz de adjacˆencia

2 1 2 2 1 5 3 4 4 3 3 4 (b) Lista de adjacˆencia Figura 2.2: Estrutura de dados para grafos

Matriz de adjacˆencia e listas de adjacˆencia s˜ao estruturas de dados b´asicas usadas para representar grafos. A figura 2.2 ilustra como seriam as representa¸c˜oes para um mesmo grafo utilizando tais estruturas.

Como podemos perceber, a matriz de adjacˆencia (figura 2.2a) ´e uma estrutura

bastante simples. A estrutura consiste numa matriz N × N, onde N ´e um n´umero de

v´ertices do grafo. O valor 1 na posi¸c˜ao (i, j) da matriz nos diz que os v´ertices i e j est˜ao ligados. Note que, alternativamente, podemos usar as posi¸c˜oes da matriz para alocarmos os pesos ou r´otulos das arestas. S˜ao algumas das vantagens dessa estrutura de dados: verificar se dois v´ertices s˜ao adjacentes, adicionar ou remover liga¸c˜oes – complexidade O(1). Todavia, temos um desperd´ıcio de mem´oria, especialmente em grafos esparsos, pois, a matriz mant´em informa¸c˜oes sobre as arestas existentes e n˜ao existentes do grafo (valores 1 e 0, respectivamente). Al´em disso, para listar as arestas incidentes a um dado v´ertice devemos percorrer todos os v´ertices – complexidade O(N). Por outro lado, as listas de adjacˆencia limitam-se a guardar somente as informa- ¸c˜oes das arestas existentes do grafo, como mostrado na figura 2.2b. Duas vantagens importantes da representa¸c˜ao baseada em listas s˜ao: (1) verificar todas as arestas in-

cidentes num dado v´ertice pode ser feito em tempo linear em rela¸c˜ao ao n´umero de

arestas1 e (2) baixo desperd´ıcio de mem´oria. Apesar disso, representar um grafo denso

1

12 Cap´ıtulo 2. Conceitos preliminares e defini¸c˜oes

com o uso de listas de adjacˆencia ´e invi´avel, pois, pode consumir uma quantidade maior de mem´oria principal comparada ao uso de matriz. Ademais, o uso dessa representa¸c˜ao ´e limitado em cen´arios onde as estruturas dos grafos n˜ao s˜ao alteradas frequentemente – remover arestas do grafo possui custo linear.

2.1.4.2 Algoritmos

Descrevemos, a seguir, trˆes algoritmos fundamentais para an´alise de grafos. S˜ao eles : (1) busca em largura , (2) busca em profundidade e (3) algoritmo de Dijkstra.

Algoritmo 1: Busca em largura

Entrada: Um grafo G e o v´ertice v a ser examinado

Sa´ıda: Os v´ertices alcan¸cados a partir de v in´ıcio

para cada u ∈ V (G) − v fa¸ca

verif [u] = −1; verif [v] = 0; S = S ∪ v;

1 enquanto S 6= ∅ fa¸ca

Selecione u ∈ S de acordo com a ordem de inser¸c˜ao;

2 S = S − u para cada n ∈ N(u) fa¸ca

se verif [n] < 0 ent˜ao verif [n] = verif [u] + 1;

3 S = S ∪ n

O algoritmo 3 descreve o m´etodo de busca em largura (breadth-first search), utilizado para realizar buscas num grafo. Nesse m´etodo, a busca ´e iniciada a partir de um v´ertice raiz e expandida, incrementalmente, para a vizinhan¸ca. Por exemplo, dado um v´ertice v como raiz, o algoritmo explora primeiro os v´ertices mais pr´oximos de v, N(v), e, posteriormente, os vizinhos de N(v) (caso eles n˜ao tenham sido examinados). Esse processo ´e repetido at´e que o v´ertice alvo seja atingido ou todos os v´ertices do grafo sejam examinados. O algoritmo apresentado visita cada v´ertice e cada aresta no m´aximo uma vez – considerando a representa¸c˜ao baseada em listas de adjacˆencia. Assim, o algoritmo executa a busca num tempo de O(V + E), al´em da complexidade de espa¸co de O(V ).

Um m´etodo recursivo para busca de profundidade (depth-first search) ´e descrito no algoritmo 2. Tal como o algoritmo de busca em largura, o m´etodo de busca em

profundidade ´e usado para pesquisar v´ertices num grafo. Esse ´ultimo, por´em, emprega

2.1. Princ´ıpios b´asicos da Teoria de Grafos 13

Algoritmo 2:Busca em profundidade

Entrada: Um grafo G e o v´ertice v a ser examinado

Sa´ıda: Os v´ertices alcan¸cados a partir de v

Verifica(v´ertice u)

1 in´ıcio

para cada n ∈ N(u) fa¸ca

se verif [n] < 0 ent˜ao verif [n] = verif [u] + 1;

Verifica(n);

Busca ()

2 in´ıcio

para cada u ∈ V (G) − v fa¸ca

verif [u] = −1; verif [v] = 0;

Verifica(v);

tices mais pr´oximos. O algoritmo inicia-se examinando um v´ertice vizinho u de v, onde v ´e o v´ertice raiz. A seguir, um v´ertice vizinho de u, ainda n˜ao explorado, ´e selecionado. Caso o v´ertice corrente n˜ao possua vizinhos ou tenha toda sua vizinhan¸ca

analisada, voltamos para o ´ultimo v´ertice examinado com vizinhos inexplorados (pro-

cedimento conhecido como backtracking), sen˜ao continuamos a busca escolhendo um de seus vizinhos. Como no caso anterior, o algoritmo de busca em profundidade tem complexidades de espa¸co e tempo de O(V ) e O(V + E), respectivamente.

Algoritmo 3:Algoritmo de Dijkstra

Entrada: Um grafo G e o v´ertice v a ser examinado

Sa´ıda: Distancia m´ınima do v´ertice v ao demais v´ertices de G

in´ıcio

para cada u ∈ V (G) − v fa¸ca

dist[u] = ∞; dist[v] = 0; S = S ∪ v;

1 enquanto S 6= ∅ fa¸ca

Selecione u ∈ S com o menor dist;

2 S = S − u para cada n ∈ N(u) fa¸ca

se dist[n] > dist[u] + (u, n) ent˜ao dist[n] = dist[u] + (u, n);

14 Cap´ıtulo 2. Conceitos preliminares e defini¸c˜oes

O algoritmo de Dijkstra ´e um dos m´etodos mais famosos para calcular os caminhos de custo m´ınimo entre v´ertices de um grafo. Escolhido um v´ertice como raiz da busca, este algoritmo calcula o custo m´ınimo (ou distˆancia m´ınima) deste para todos os demais v´ertices do grafo. Inicialmente, todos os nodos tem um custo infinito, exceto v (a raiz da busca) que tem valor 0. A seguir, os vizinhos de v s˜ao examinados e, caso suas distˆancias para v sejam atualizadas (ou seja, distˆancias menores para v foram encontradas), eles s˜ao colocados em uma fila. O pr´oximo v´ertice a ser expandido ´e aquele cuja distˆancia para v ´e a menor poss´ıvel, dentre os v´ertices da fila. Uma vez expandido, o v´ertice ´e removido da fila. Esse processo continua enquanto existir v´ertice na fila. Note que o algoritmo de Dijkstra ´e similar `a estrat´egia de busca em largura,

por´em, ele emprega uma estrat´egia para selecionar o pr´oximo v´ertice a ser expandido2.

Dijkstra pode ser implementado de forma eficiente usando uma estrutura heap, sendo executado em O(|E|log|V |).

No documento Similaridade de grafos via hashing (páginas 32-36)

Documentos relacionados