Exame tipo resolvido

Propaganda
LICENCIATURA EM ENGENHARIA INFORMÁTICA E COMPUTAÇÃO
Algoritmos e Estruturas de Dados II, 2002/2003
EXAME TIPO
COM CONSULTA
DURAÇÃO: 2 horas
1.
[2.0] Mostre o resultado final de inserir numa tabela de dispersão de tamanho N=13, inicialmente
vazia, os valores 16, 4 e 29, por esta ordem, usando a função de dispersão H(X) = X mod 13 e dispersão
aberta com teste quadrático para resolução de colisões.
2.
[2.0] Mostre o estado de um heap binário (na representação em árvore) inicialmente vazio após a
realização de cada uma das seguintes operações: insert(10), insert(5), insert(12), insert(3), deleteMin().
3. [2.0] Mostre o resultado final de inserir numa árvore k-d inicialmente vazia os pontos (3,5), (8,2), (4,
3), (2, 5) e (1, 7), por esta ordem.
4.
[2.0] Suponha que se pretende contar o número de palavras diferentes existentes numa lista
desordenada de palavras. É possível resolver este problema em tempo linear no tamanho da lista? Com
que estrutura de dados? Justifique.
5.
[2.0] Suponha que se pretende guardar um conjunto de valores numa estrutura de dados suportando
eficientemente as seguintes operações:
i) verificar se um valor pertence ao conjunto;
ii) inserir um novo valor no conjunto;
iii) eliminar um valor do conjunto;
iv) obter o valor mínimo ou o valor máximo existente no conjunto;
v) obter uma lista ordenada dos valores existentes no conjunto entre um valor mínimo e um valor
máximo especificados;
vi) reunir dois conjuntos num só (sem valores repetidos).
Que estrutura de dados estudada na disciplina seria mais apropriada para este efeito? Com essa estrutura
de dados, qual seria a complexidade temporal, no pior caso e no caso médio, de cada uma das operações
acima indicadas? Justifique.
6. [2.0] Assinale os componentes fortemente conexos do grafo indicado na figura seguinte.
i
a
c
e
d
f
g
b
k
h
j
7. [2.0] Dado um grafo dirigido com custos não negativos associados às arestas, pretende-se encontrar um
caminho de custo mínimo de um vértice s para um vértice t, passando obrigatoriamente, uma e uma só
vez, por vértices intermédios x1, ..., xk, pela ordem indicada (podendo passar mais do que uma vez por
outros vértices). Explique de que forma este problema pode ser resolvido eficientemente com base em
algoritmos estudados na disciplina e indique, justificando, em quanto tempo pode ser resolvido o
problema, em notação O(). A figura seguinte exemplifica um caminho de custo mínimo deste tipo.
x2
1
s
a
3
Caminho:
t
3
s-a-x1-a-x2-a-t
1
2
5
5
1
2
x1
1
Pagina 1 de 6
8.
[2.5] Um grafo G=(V,E) diz-se bipartido se é possível partir o conjunto V de vértices em dois
subconjuntos V1 e V2 disjuntos de tal forma que quaisquer dois vértices adjacentes em G pertencem a
subconjuntos diferentes. Por exemplo, o grafo G1 da figura seguinte é bipartido, enquanto que o grafo G2
não é bipartido (na realidade, o grafo G2 é tripartido).
G1
G2
V1
V2
1
2
3
4
V1
1
V2
2
5
V3
3
6
4
O problema de verificar se um grafo não dirigido é bipartido e, em caso afirmativo, encontrar uma
possível partição dos vértices, pode ser resolvido eficientemente com base no algoritmo de visita em
profundidade, de que se recorda a seguir uma implementação em pseudo-Java (na realidade, C#).
class Graph
{
// ...
public void dfs()
{
foreach (Vertex v in V) // V - vértices de G
v.visited = false;
foreach (Vertex v in V)
if (! v.visited)
dfs(v);
}
private void dfs(Vertex v)
{
v.visited = true;
foreach (Vertex w in v.adj) // adj - vértices adjacentes
if(! w.visited)
dfs(w);
}
}
Escreva em Java ou pseudo-Java um método isBipartite(), baseado na pesquisa em profundidade,
que devolve true no caso do grafo ser bipartido e, adicionalmente, preenche a propriedade
v.partition (de tipo int) de cada vértice v com o número do subconjunto (V1 ou V2) em que o
vértice é colocado.
9.
[2.5] Esboce em Java ou pseudo-Java um algoritmo baseado em retrocesso (backtracking) para
verificar se dois grafos G1 e G2 são isomorfos. Dois grafos dizem-se isomorfos se é possível estabelecer
uma correspondência entre os vértices dos dois grafos, de forma a que, para cada aresta (u,v) num dos
grafos, existe uma aresta (u*,v*) no outro grafo, em que u* é o vértice correspondente a u e v* é o vértice
correspondente a v. Na figura seguinte, apenas os grafos G1 e G2 são isomorfos.
G2
G1
a
c
b
d
x
z
Pagina 2 de 6
G3
y
y
x
w
z
w
Resolução:
1.
H(16)=3
H(4)=4
H(29)=3  como a posição 3 está ocupada, tenta em 3+12=4, que também está ocupada,
e depois em 3+22=7
Índice
0
1
2
3
4
5
6
7
8
9
10
11
12
Conteúdo
16
4
29
Nota: Basta apresentar a tabela, mas, em caso de erro, a explicação inicial pode ajudar.
2.
Nota prévia: como se fala em deleteMin, supõe-se que é um heap que guarda o mínimo à cabeça.
insert(10)
insert(5)
10
10
5
insert(3)
percolateUp
5
10
3
12
insert(12)
percolateUp
5
10
10
12
12
percolateDown
deleteMin()
3
5
5
10
5
5
12
10
12
10
Nota: não é necessário mostrar os estados intermédios (indicados a tracejado), mas ajudam a
perceber erros.
Pagina 3 de 6
3.
(3,5)
(8,2)
(2,5)
(4,3)
(1,7)
4.
Sim, é possível resolver este problema em tempo linear no tamanho da lista, em termos médios,
utilizando uma tabela de dispersão, da seguinte forma:
 Começa-se com uma tabela de dispersão (T) inicialmente vazia e com um contador de palavras
diferentes (K) inicialmente a 0.
 Percorrem-se sequencialmente os elementos da lista (L) e, para cada elemento, verifica-se se
existe na tabela de dispersão. Em caso afirmativo, passa-se ao elemento seguinte. Em caso
negativo, incrementa-se o contador de palavras diferentes e insere-se o elemento na tabela de
dispersão.
Sendo N o tamanho da lista e K o número de palavras diferentes, há que somar os seguintes tempos:
O(N) - percorrer a lista (caso médio e pior caso)
N * O(1) = O(N) - verificar se elemento existe na tabela de dispersão (caso médio)
K * O(1) = O(K) - inserir elemento na tabela de dispersão (caso médio)
Uma vez que KN, o tempo total é O(N), em média.
5.
Uma boa solução de compromisso seria uma árvore binária equilibrada (por exemplo, árvore AVL),
conforme mostra a tabela seguinte. Se bem que uma tabela de dispersão seja um pouco melhor (só apenas
no caso médio), em algumas operações, é muito pior nas operações que se baseiam na ordenação (iv e v).
Operação
Tempo com árvore AVL, no Tempo
com
tabela
de
pior caso e caso médio
dispersão, no caso médio
i) verificar se um valor pertence O(log N)
O(1)
ao conjunto
ii) inserir um novo valor no O(log N)
O(1)
conjunto
iii) eliminar um valor do O(log N)
O(1)
conjunto
iv) obter o valor mínimo ou o O(log N)
O(N) (caso médio e pior caso)
valor máximo existente no
conjunto
v) obter uma lista ordenada dos O(R+log N), em que R é o O(N + R log R) (caso médio e
valores existentes no conjunto tamanho do resultado. A parcela pior caso), em que R é o
entre um valor mínimo e um log N refere-se ao acesso a tamanho do resultado. O tempo
valor máximo especificados
elementos que não fazem parte O(N) refere-se à selecção dos
do resultado (no máximo 1 valores no intervalo pretendido,
elemento de cada nível pela e o tempo O(R log R) refere-se à
esquerda e pela direita).
ordenação dos valores.
vi) reunir dois conjuntos num só O[N2log(N1+N2-Ncomuns)],
O(N2), supondo que se inserem
(sem valores repetidos)
supondo que se inserem os os elementos do 2º conjunto no
elementos do 2º conjunto no 1º
1º
Nota: não é necessário indicar os tempos da tabela de dispersão.
Pagina 4 de 6
6. O grafo tem os 4 componentes fortemente conexos indicados por rectângulos de cantos arredondados
na figura.
i
a
c
d
e
f
g
k
h
b
j
7. O problema pode ser resolvido por aplicação repetida do algoritmo de Dijkstra:

determinar o caminho de custo mínimo (ou mais curto) de s para x1, considerando eliminados do
grafo (do ponto de vista lógico) os vértices x2, ..., xk;
 para i=1, ..., k-1, determinar o caminho de custo mínimo de xi para xi+1, considerando eliminados
do grafo (do ponto de vista lógico) os vértices x1, xi-1,..., xi+1, xk;
 determinar o caminho de custo mínimo de xk para t, considerando eliminados do grafo (do ponto
de vista lógico) os vértices x1, ..., xk-1.
Para determinar o caminho mais curto (ou de custo mínimo) entre dois vértices, usa-se o algoritmo de
Dijkstra, o qual determina todos os caminhos mais curtos entre um dado vértice e todos os restantes.
Uma vez que o tempo de execução de cada aplicação do algoritmo de Dijkstra é de ordem O(|E| log |V|), e
o algoritmo é aplicado k+1 vezes, o tempo total de resolução do problema é de ordem O((k+1)|E| log |V|).
8.
class Graph
{
/** Verifica se o grafo é bipartido. */
public bool isBipartite()
{
foreach (Vertex v in V) // V - vértices de G
v.partition = 0; // ainda não atribuido
foreach (Vertex v in V)
if (! v.partition)
if ( ! dfs2(v, 1) )
return false;
return true;
}
/**
* Efectua visita e define partição de cada vértice.
* @param v - vértice a visitar, bem como adjacentes
* @param partition - partição (1 ou 2) em que deve colocar
*
este vértice
**/
private bool dfs2(Vertex v, int partition)
{
v.partition = partition;
partition = (partition==1)? 2 : 1; // para adjacentes
foreach (Vertex w in v.adj) // adj - vértices adjacentes
if(! w.partition)
dfs(w, partition);
else if (w.partition != partition)
return false;
return true;
}
}
Pagina 5 de 6
9.
Nota: neste esboço de resolução apenas é detalhada a estratégia de backtracking.
static bool isomorfos(Graph G1, Graph G2)
{
if (G1.V.size()! = G2.V.size())
return false;
foreach(Vertex v in G1)
v.image = null;
foreach(Vertex v in G2)
v.image = null;
return isomorfos_rec(G1,G2);
}
// Tenta definir correspondente para 1 vértice de G1
// e chamar-se recursivamente para os restantes.
static bool ismorfos_rec(Graph G1, Graph G2)
{
v1 = select1(Vertex v1 in G1 such that v1.image==null);
if (v1 == null)
return true;
foreach(Vertex v2 in G2 such that v2.image == null
&& nonnull(image(v1.adj)) == nonnull(v2.adj)
&& nonnull(image(v1.invadj)) == nonnull(v2.invadj))
// v.adj - conjunto de vértices adjacentes de v
// v.invadj - conjunto de vértices de que v é adjacente
// image(...) - aplicado a conjunto de vértices, dá o
//
conjunto das suas imagens
// nonnull(...) - retira nulls's de conjunto
{
v1.image = v2;
v2.image = v1;
if (isomorfos_rec(G1, G2))
return true;
v1.image = null;
v2.image = null;
}
return false;
}
Pagina 6 de 6
Download