6. Pesquisa e Ordenação Pesquisa de Informação

Propaganda
6. Pesquisa e Ordenação
Fernando Silva
DCC-FCUP
Estruturas de Dados
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
1 / 30
Pesquisa de Informação
A pesquisa eficiente de informação é extremamente relevante, seja:
pesquisa num catálogo indexado por uma relação de ordem, e.g.
alfabética, como seja uma lista telefónica;
pesquisa interna nos registos de uma base de dados: registos
ordenados ou não ordenados;
pesquisa de informação em páginas Web (pesquisa de texto);
pesquisa de informação em dados binários, normalmente imagens, etc.
A pesquisa sequencial é dos casos mais simples e é normalmente usada
quando não se tem uma relação de ordem na informação a pesquisar.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
2 / 30
Pesquisa Sequencial
A pesquisa sequencial consiste em procurar um valor x numa
sequência de valores v [] com dimensão N.
Vejamos a pesquisa com valores inteiros e strings (veremos mais tarde
como fazer o mesmo com apenas um método):
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
3 / 30
Pesquisa Binária
A pesquisa binária é uma estratégia eficiente de pesquisa de um valor x
numa sequência ordenada de valores v [] indexado no intervalo (e, d):
Ideia do algoritmo:
Um exemplo:
Seja m a posição média de v[]
Comparar x com v[m]
I
I
I
Se x==v[m] então encontrou
senão se x<v[m], procura x no
intervalo [e,m-1]
senão (x>v[m]), procura x no
intervalo [m+1,d]
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
4 / 30
Pesquisa Binária: versão recursiva
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
5 / 30
Estruturas de Dados
6 / 30
Pesquisa Binária: versão não recursiva
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Pesquisa Indirecta
Seja int o[] um vector que determina a ordem dos elementos de uma
sequência de nomes String nomes[]. Como pesquisar a string nome no
vector nomes[]?
Efectuar pesquisa binária dos nomes através do vector auxiliar o[] que
define a ordem dentro de nomes[].
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
7 / 30
6. Pesquisa e Ordenação
Estruturas de Dados
8 / 30
Pesquisa Indirecta
Fernando Silva (DCC-FCUP)
Algoritmos de Ordenação
Em que é que a ordenação pode ajudar para resolver tarefas importantes
de programação?
Verificar unicidade – Como verificar se os elementos de um conjunto
S são todos distintos?
I
Ordenando S, os elementos repetidos ficam seguidos, pelo que basta
verificar se S[i] = S[i + 1] para algum 1 ≤ i < n.
Remover repetições – Como remover todas as repetições de um
dado elemento de S?
I
Ordenar S e depois percorrer os seus elementos com 2 cursores.
Prioritizar eventos – Suponha que são dados um conjunto de tarefas
para fazer, cada uma com o seu prazo. Ordenar os eventos de acordo
com a data de “deadline” permite colocar as tarefas na ordem
correcta.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
9 / 30
Algoritmos de Ordenação (cont.)
Média/Selecção – suponha-se que se pretende o k-ésimo item do
conjunto S.
I
Ordenar por ordem crescente. O valor procurado está em S[k].
Contagem/frequência – Qual é o elemento mais frequente de S.
Intersecção/Reunião – a operação é trivial se os conjuntos
estiverem ordenados.
Procura eficiente – como verificar se um dado elemento x pertence
a um conjunto S?
I
Se esta for uma operação frequente, compensa ordenar primeiro para
depois usar pesquisa binária.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
10 / 30
Método de ordenação: selecção de máximo/mínimo
Na posição i do vector v [], coloca-se o maior (ou menor) elemento entre
os ainda não ordenados, i.e. que se encontram entre i + 1 e n − 1
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
11 / 30
Ordenação Indirecta
Considere um vector com 4 objectos, cada um representando uma pessoa
com nome, ano e local de nascimento, ordenados por ano de nascimento.
Como obter esta informação ordenada, por ordem alfabética dos nomes
das pessoas, sem alterar o vector original?
Usar um vector auxiliar O[] que contenha a ordenação do vector original?
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
12 / 30
Ordenação Indirecta (cont.)
Usando o método de ordenação por selecção de mínimo e admitindo que a
classe Pessoa tem atributos nome, anonasc e concelho.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
13 / 30
Método de ordenação: inserção
Este método de ordenação é designado de “inserção” porque, em cada
passo, procura inserir um novo elemento na posição correcta de uma
sequência já ordenada. Os passos associados ao método são:
Supor que o vector v[] está já parcialmente ordenado (posições 0 a
p-1);
adicionar um novo elemento não ordenado é simples:
I
I
I
basta ir de v[p] até v[0] para determinar a posição k do novo valor;
deslocar os elementos entre v[k+1] e v[p];
adicionar o valor em v[k]
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
14 / 30
Método de ordenação: inserção
O algoritmo pode ser simplificado se usarmos a posição 0 do vector com
um valor de paragem (mais pequeno que qualquer outro do vector;
supondo ordenação crescente):
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
15 / 30
Método de ordenação1: bolha (bubble-sort)
Este método consiste em comparar os elementos do vector dois a dois e
trocar os elementos que não estiverem na ordem desejada.
O nome vem do facto de em
cada iteração as comparações
sucessivas de elementos
deslocarem o maior (ou menor)
elemento para as últimas
posições do vector como se
fosse o deslizar de uma bolha.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
16 / 30
Método de ordenação2: bolha (bubble-sort)
O algoritmo 1, faz sempre n(n − 1)/2 comparações. Se o vector ficar
ordenado a meio das iterações, faz comparações desnecessárias.
Uma optimização consiste em
usar uma flag que sinaliza a
ocorrência de trocas numa
iteração. O algoritmo termina
se não ocorrerem trocas na
iteração anterior.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
17 / 30
Método de ordenação3: bolha (bubble-sort)
Uma melhoria adicional é
recordar em cada iteração onde
se verificou a última troca e
fazer o ciclo-j ir só até essa
posição na iteração seguinte:
As diferenças na eficiência destes 3 algoritmos de bubblesort só serão
visíveis para valores grandes de n.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
18 / 30
Ordenação: Método Quick-Sort
O quicksort é um dos algoritmos de ordenação mais eficiente (O(n log n)).
Baseia-se numa estratégia recursiva dividir-para-conquistar. Supondo que
se pretende ordenar um vector S, consiste em:
1
2
3
4
Se o número de elementos em S é 0 ou 1, S está ordenado;
Escolher um elemento v ∈ S. Chamamos-lhe pivot.
Dividir S − v em dois vectores:
S1 = {x ∈ S − {v } | x < v }, elementos menores que o pivot
S2 = {x ∈ S − {v } | x ≥ v }, elementos maiores que o pivot
Note-se que os elementos em S1 e S2 não estão necessariamente
ordenados.
Aplicar recursivamente o algoritmo a S1 e S2
Neste algoritmo, o esforço está na partição do vector, sendo a estratégia
de escolha do pivot importante. A junção dos sub-vectores já ordenados é
uma simples colagem.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
19 / 30
Estruturas de Dados
20 / 30
Ilustração do Algoritmo Quicksort
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Implementação do quick-sort
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
21 / 30
Implementação do quick-sort (cont.)
Um método para concretizar a partição do vector, consiste em usar dois
cursores a e b que inicialmente correspondem às extremidades do vector.
Os cursores são deslocados em direcções opostas de forma a separarem os
elementos menores que o pivot dos elementos maiores ou iguais. As
decisões a tomar são:
Se v [a] < pivot então a = a + 1
Se v [b] ≥ pivot então b = b − 1
Troca v [a] com v [b] e incrementa a e b
A partição está completa quando b < a.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
22 / 30
Implementação do quick-sort (cont.)
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
23 / 30
Optimização do Algoritmo Quicksort
O quicksort é menos eficiente do que outros métodos para valores
pequenos de N (número de elementos no vector). Assim, uma estratégia
para melhorar ainda mais o desempenho do quicksort, é evitar que ele seja
aplicado quando os sub-intervalos atingem um valor relativamente baixo 10
a 15 elementos, e nesses casos usar outro método. Teríamos algo como:
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
24 / 30
Ordenação: Método Mergesort
A ideia base do algoritmo consiste em:
subdivide o vector em duas partes,
aplicar o algoritmo a cada parte,
quando as duas partes estiverem ordenadas (2 vectores ordenados),
faz-se a junção para produzir um vector final ordenado.
6 24 28 3 13 10 7 30 22 16 8 25 12 5
separa em 2 vectores
3 6 7 10 13 24 28 5 8 12 16 22 25 30
mergesort de cada vector
3 6 7 10 13 24 28 5 8 12 16 22 25 30
junta as listas ja ordenadas.
3 5
6 7
8 10 12 13 16 22 24 25 28 30
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
25 / 30
Algoritmo mergesort - exemplo divide-and-conquer
Exemplo típico da técnica de programação dividir-para-conquistar.
procuramos dividir o nosso problema em sub-problemas mais
pequenos que sabemos resolver e depois juntamos os resultados dos
sub-problemas para obter o resultado final.
subdividir o vector inicial em sub-vectores até termos dimensão 1.
Juntar ordenadamente dois vectores de dimensão 1 é fácil, podemos
depois juntar dois vectores de dimensão 2, etc.
O método principal consiste em:
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
26 / 30
Mergesort - junção das partes
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
27 / 30
Funções de ordenação do Java
Usar a class java.util.Arrays que contém vários métodos para
ordenar, e.g.
static void sort(Object[] a)
static void sort(Object[] a, Comparator c)
Existem outros métodos específicos para inteiros ou strings.
Em Java, a classe Arrays permite a invocação do método sort()
para ordenar não apenas inteiros mas outro tipo de objectos. Para tal,
os objectos têm de pertencer a classes que implementem a interface
Comparable:
public interface Comparable {
int compareToObject(Object o);
}
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
28 / 30
Funções de ordenação do Java (cont.)
Como exemplo, suponhamos que temos a seguinte classe:
class Pessoa implements Comparable {
String nome;
int idade;
...
public int compareTo(Object o) {
Pessoa outra= (Pessoa) o;
if (idade < outra.idade) return -1;
if (idade > outra.idade) return 1;
return 0;
}
}
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
29 / 30
Funções de ordenação do Java
Deste modo, se tivermos um vector de objectos do tipo Pessoa é possível
ordenar:
Pessoa p[]= new Pessoa[N];
...
Arrays.sort(p); //ordena o vector de objectos Pessoa por idade
É ainda possível melhorar este código com os genéricos do Java.
Fernando Silva (DCC-FCUP)
6. Pesquisa e Ordenação
Estruturas de Dados
30 / 30
Download