Departamento de Computao e Matemtica 2 Semestre/2012 Prof. Dr. Jos Augusto Baranauskas Notas de Aula
Busca em Vetores
A busca est entre as tarefas mais frequentemente encontradas em programao de computadores. A hiptese bsica assumida no processo de busca que o conjunto de dados, dentre o qual um determinado elemento deve ser procurado, possui tamanho fixo.
Notao
Assume-se que o conjunto de dados a ser pesquisado seja representado atravs de um vetor a de, no mximo de N elementos (a[0], a[1], ..., a[N-1]), por exemplo, como:
item a[N];
Normalmente, item representa uma estrutura de dados contendo um campo que atua como chave para a pesquisa. Assim, item poderia representar o registro de um funcionrio contendo seu nmero de matrcula, grau de escolaridade, estado civil e seo onde trabalha:
const int N = 100; typedef struct item { int matricula; // chave de busca int escolaridade; // demais campos da estrutura char ecivil; int secao; }; item a[N];
De forma geral, podemos representar o item da seguinte forma:
typedef struct item { int key; // chave de busca ... // demais campos da estrutura };
O objetivo da busca consiste ento em encontrar um elemento do vetor a cujo campo de busca (a chave) seja igual a um argumento de busca x fornecido. O ndice i resultante, que satisfaz a condio a[i].key == x permite ento o acesso aos demais campos. Como o interesse bsico desse estudo est exclusivamente no processo de busca, no sendo importante o tipo de dado associado chave, vamos admitir que o tipo item seja composto apenas do campo chave, ou seja, o dado a prpria chave. Alm disso, para facilitar o estudo ainda mais, a chave de busca ser um inteiro, ou seja, o vetor a ser declarado como:
int a[N];
Busca Linear (ou Busca Sequencial)
Nos casos em que no se dispe de informaes adicionais sobre os dados a serem pesquisados o procedimento mais bvio uma busca sequencial por todo o vetor, aumentando-se desta maneira passo a passo o tamanho da regio do vetor em que o elemento procurado no se encontra. Este procedimento chamado de busca linear. Uma busca linear termina quando for satisfeita uma das duas condies seguintes:
2 1. O elemento encontrado, isto , a[i] == x. 2. Todo o vetor foi analisado, mas o elemento x no foi encontrado.
Isto resulta no algoritmo a seguir:
i = 0; while (i < N && a[i] != x) i++;
Note que relevante a ordem dos termos na expresso booleana. Ao trmino do comando while, tem-se duas possibilidades: i == N, indicando que o elemento x no foi encontrado ou a[i] == x, e i indica a posio onde x foi encontrado no vetor a.
Anlise da Busca Linear: Em mdia so efetuadas N/2 comparaes de chaves para encontrar um elemento particular x no vetor a de N elementos. O pior caso requerer N comparaes. Isso pode consumir muito tempo quando o nmero de elementos do vetor grande.
Busca Linear com Sentinela
Obviamente cada passo requer o incremento do ndice i e a avaliao de uma expresso booleana. O problema seguinte consiste em verificar se esta tarefa pode ser simplificada e, portanto, a busca acelerada. A nica possibilidade de se obter tal efeito consiste em se encontrar uma simplificao da expresso booleana, que depende essencialmente de dois fatores.
Dessa forma, preciso estabelecer uma condio baseada em um nico fator que implique nos dois fatores dos quais depende a expresso. Isto possvel desde que se possa garantir que o elemento x seja encontrado. Para tanto, introduz-se um elemento adicional, com o valor x, no final do vetor. Esse elemento auxiliar d-se o nome de sentinela, porque ele evita que a busca avance o limite do tamanho do vetor. O vetor a ser ento declarado como:
item a[N+1];
e o algoritmo de busca linear com sentinela torna-se:
i = 0; a[N] = x; while (a[i] != x) i++;
Evidentemente, i == N implica que x no foi encontrado (exceto o correspondente sentinela).
Anlise da Busca Linear com Sentinela: Em mdia so efetuadas (N+1)/2 comparaes para encontrar um elemento particular x no vetor a de N elementos. O pior caso requerer N+1 comparaes.
Busca Binria
bvio que no existem meios de acelerar uma busca sem que se disponha de maiores informaes acerca do elemento a ser localizado. Suponha, por exemplo, uma lista telefnica em que os nomes no estejam em ordem alfabtica. Uma coisa dessas seria completamente intil. Sabe-se tambm que uma busca pode ser mais eficiente se os dados estiverem ordenados. A seguir ser apresentado um algoritmo que explorar o fato do vetor estar ordenado, ou seja, a[0] a[1] a[N-1].
A ideia principal a de teste um elemento sorteado aleatoriamente, por exemplo, a[m] e compar-lo com o elemento de busca x. Se tal elemento for igual a x, a busca termina. Se for menor que x, conclui-se que todos os elementos com ndices menores ou iguais a m podem ser eliminados dos prximos testes. Se for maior 3 que x, todos aqueles elementos com ndices maiores ou iguais a m podem ser tambm eliminados da busca. Isso resulta no algoritmo seguinte, denominado busca binria, pois a cada passo, o vetor dividido em duas partes cada vez menores. O algoritmo utiliza duas variveis L e R que marcam os limites esquerdo e direito, respectivamente, da regio de a em que um elemento igual a x ainda pode ser encontrado.
L = 0; R = N - 1; achou = false; while (L <= R && ! achou) { m = qualquer valor entre L e R; if (a[m] == x) achou = true; else if (a[m] < x) L = m + 1; else R = m - 1; }
Embora a escolha de m seja aparentemente arbitrria (no sentido que o algoritmo funciona independentemente dele) o valor desta varivel influencia na eficincia do algoritmo. claro que, a cada passo, deve-se eliminar o maior nmero possvel de elementos em futuras buscas. A soluo tima escolher a mediana dos elementos, porque ela elimina, em qualquer caso, metade dos elementos do vetor.
A eficincia pode ser ligeiramente melhorada atravs da permutao entre as duas clusulas de comparao. A condio de igualdade deve ser testada em segundo lugar, porque o sucesso ocorre apenas uma vez em todo o processo. Porm, a questo mais relevante se refere ao fato de, como na busca linear, se poder ou no encontrar uma soluo que proporcione uma condio mais simples para a finalizao do processo. possvel obter tal algoritmo rpido de busca binria se for abandonada a meta de terminar a busca no instante exato em que for encontrado o elemento pesquisado. Isso parece pouco inteligente primeira vista, mas observando-se mais a fundo, pode-se perceber facilmente que o ganho em eficincia em cada passo ser maior do que a perda ocasionada pela comparao de alguns poucos elementos adicionais. Assim, o algoritmo fica:
L = 0; R = N - 1; while (L < R) { m = (L + R) / 2; if (a[m] < x) L = m + 1; else R = m; }
Se ao trmino do algoritmo a condio a[R] == x for verdadeira, ento x foi encontrado na posio R de a; caso contrrio x no foi encontrado.
Anlise da Busca Binria: Assumindo que m seja calculado como (L+R)/2, no melhor caso efetuada apenas uma comparao. Em mdia so efetuadas
) 2 / ) 1 (( log 2 2 + N comparaes para encontrar um elemento particular x no vetor a de N elementos. O pior caso requerer
) 1 ( log 2 2 + N comparaes.
Anlise da Busca Binria Rpida: Em mdia e no melhor caso so efetuadas
1 ) ( log ) 2 / ( log 2 2 = N N comparaes para encontrar um elemento particular x no vetor a de N elementos. O pior caso requerer
) ( log 2 N comparaes.
4 Comparao dos Mtodos de Busca
Considerando os algoritmos de busca vistos, a tabela seguinte mostra a ordem de grandeza dos nmeros mnimo (C mn ), mdio (C md ) e mximo (C mx ) de comparaes de chaves.
Das anlises dos algoritmos de busca, est claro que o mtodo de busca binria tem um desempenho to bom, ou melhor, do que o mtodo de busca linear. Entretanto, a atualizao dos ndices esquerdo, direito e mdio (L, R e m no algoritmo, respectivamente) requer tempo adicional. A figura seguinte mostra o comportamento dos dois mtodos de busca.
Busca Binria Busca Linear Nmero de elementos (N) Nmero de comparaes Busca Binria Busca Linear Nmero de elementos (N) Nmero de comparaes