Pesquisa Pesquisa: localização de um Registo num Ficheiro (para aceder ao registo: ler/alterar informação) Ficheiro (ou tabela) Campos Nome Endereço Telefone Antunes, João A. R. P. António Viera, 23 720456 Baptista, Vitor C. R. Carlos Seixas, 9, 6º 705423 Melo, Eurico R. Quinta Nova, L12, B 346512 Registos Pereira, Maria A. Lrg. da Portagem, 12, 4º 20345 Silva, José A. R. das Padeira, 23, 3º 816524 Ficheiro de tamanho n: sequência de n items r(1), r(2), r(3)... r(n) designados por registos Registos: divididos em campos (no ex: nome, endereço, telefone) António José Mendes - Programação e Algoritmos II 210 Chave A cada registo está associada uma chave, que serve para diferenciar os registos; A associação de uma chave a um registo pode ser simples ou complexa; Na sua forma mais simples, a chave consiste num dos campos do registo; Uma outra alternativa consiste numa tabela separada contendo as chaves e os ponteiros para os registos respectivos. Chave primária: quando todos os registos têm uma chave diferente Chave secundária: quando há mais do que um registo com a mesma chave António José Mendes - Programação e Algoritmos II 211 1
Algoritmos de pesquisa Algoritmo de pesquisa: aceita uma chave a e tenta encontrar um registo cuja chave seja igual a a. Todo o registo, ou Devolve Um ponteiro para o registo, ou Registo vazio ou ponteiro nulo no caso de não ter sido encontrado nenhum registo para a chave fornecida Algoritmo de pesquisa e inserção: no caso da pesquisa não ser bem sucedida insere na tabela o registo correspondente à chave pesquisada. António José Mendes - Programação e Algoritmos II 212 Organização dos ficheiros Os ficheiros (ou tabelas) podem estar organizados de diversas formas: array lista ligada árvore outras... Em regra, uma dada técnica de pesquisa pressupõe também uma forma específica de organização do ficheiro Pesquisa interna: todo o ficheiro está em memória central Pesquisa externa: o ficheiro (ou parte) está em memória secundária. António José Mendes - Programação e Algoritmos II 213 2
Pesquisa sequencial Aplicável a uma tabela (organizada como um array ou como uma lista ligada ). Seja K uma array de n chaves e r um array de registos tal que k(i) é a chave de r(i); Seja o argumento de pesquisa chave; A variável pesquisa conterá o menor inteiro i tal que k(i)=chave, se i existir, e conterá -1 se i não existir. static int pesquisa_seq (int t[], int chave, int n) { int j; for (j = 0; j < n; j++) if (chave == t[j]) return (j); return (-1); } António José Mendes - Programação e Algoritmos II 214 Eficiência da pesquisa sequencial O número de comparações necessário para encontrar um registo numa tabela de dimensão n é, obviamente, dependente da posição do registo na tabela (1 comparação para o 1º registo; n para o último). Em média, o número de comparações é (n + 1)/2 É possível diminuir o número médio de comparações colocando os registos acedidos mais frequentemente no início da tabela António José Mendes - Programação e Algoritmos II 215 3
Pesquisa numa tabela ordenada O ordenamento da tabela de chaves (e da tabela de registos), por ordem crescente ou decrescente, permite tornar as pesquisas muito mais eficientes. Existem diversas técnicas para tirar partido da ordenação, tornando as pesquisas mais rápidas. Algumas das técnicas, no entanto, impõem que o tamanho da tabela seja fixo, ou, pelo menos, tornam-se muito complexas se o tamanho da tabela variar. Uma vantagem imediata da ordenação obtêm-se no caso em que o elemento pesquisado não faz parte da tabela. Numa tabela não ordenada são necessárias n comparações para concluir que o elemento não existe, enquanto que numa tabela ordenada bastam n/2 (em média), assumindo que as chaves a pesquisar se distribuem uniformemente. António José Mendes - Programação e Algoritmos II 216 Pesquisa sequencial indexada Método para melhorar a eficiência da pesquisa numa tabela ordenada por ordem crescente É criada uma tabela auxiliar ordenada por ordem crescente da chave (tal como a tabela principal) Cada elemento da tabela de índices consiste num chave (Kindice) e num ponteiro para o registo da tabela que corresponde a Kindice A tabela de índices tem 1/m do tamanho da tabela principal. No exemplo m = 8, ou seja a tabela índice tem 1/8 do tamanho da principal. Os registos representados na tabela de índices estão espaçados de m em m. Kindice Índice Pindice k (Chave) António José Mendes - Programação e Algoritmos II 217 8 14 26 38 72 115 306 329 387 409 512 540 567 583 602 611 618 741 798 811 814 r (Registos) 4
Pesquisa sequencial indexada: método Método: A pesquisa é feita primeiro na tabela de índices; Assim que o índice correcto é encontrado a pesquisa continua na tabela principal; Na tabela principal a pesquisa restringe-se a uma pequena zona de tamanho m (8 elementos no exemplo ao lado). Vantagens: Permite reduzir o tempo de pesquisa; É utilizada uma simples pesquisa sequencial. Inconvenientes: Kindice A inserção e o apagamento de novos elementos é mais complicada (utilização de flags no apagamento). Índice Pindice k (Chave) António José Mendes - Programação e Algoritmos II 218 8 14 26 38 72 115 306 329 387 409 512 540 567 583 602 611 618 741 798 811 814 r (Registos) Pesquisa sequencial indexada: tabelas muito grandes Índice Secundário 824 999 Para tabelas muito grandes é possível utilizar várias tabelas de índice Índice Primário 824 923 987 999 k (Chave) 8 14 26 38 72 115 306 329 387 409 512 540 567 583 602 611 618 741 798 811 814 824 836 856 887 891 902 914 917 923 r (Registos) António José Mendes - Programação e Algoritmos II 219 5
Pesquisa binária Método: A chave da pesquisa é comparada com a chave do registo a meio da tabela Se forem iguais -> fim da pesquisa; Se não, continua-se a pesquisa na metade superior ou inferior da tabela, consoante o resultado a chave de pesquisa for maior ou menor do que a chave do registo a meio da tabela; A pesquisa binária pode ser efectuada na tabela principal ou então utilizada conjuntamente com a tabela sequencial indexada. Eficiência: O número máximo de comparações é log 2 n. Limitação: A pesquisa binária só pode ser utilizada se a tabela estiver sob a forma de um array estático. António José Mendes - Programação e Algoritmos II 220 Pesquisa binária static int pesquisa_bin (int t[], int chave, int n) { int low, hi, meio; low = 0; hi = n-1; while (low <= hi) { meio = (low + hi) / 2; if (chave == t[meio]) return (meio); if (chave < t[meio]) hi = meio - 1; else low = meio + 1; } return (-1); } António José Mendes - Programação e Algoritmos II 221 6
Pesquisa em Java O Java API inclui já algumas funções de pesquisa que se encontram na classe java.utils. Arrays Existe uma função binarysearch que implementa o algoritmo de pesquisa binária sobre tabelas de vários tipos Esta função recebe a tabela e a chave a pesquisar António José Mendes - Programação e Algoritmos II 222 7