Uma das tarefas mais comuns em programação é encontrar uma informação específica dentro de um grande conjunto de dados. Imagine procurar uma palavra em um dicionário: você abriria na primeira página e leria palavra por palavra? Ou abriria no meio e decidiria para que lado ir? Esta aula apresenta duas estratégias para um computador fazer exatamente isso: a busca linear (o método sequencial) e a busca binária (o método inteligente).
Este é o método mais simples e intuitivo. Ele funciona como um detetive que verifica cada casa de uma rua, uma por uma, começando do número 1, até encontrar o que procura. Em um vetor, o programa começa no índice 0 e avança posição por posição, comparando cada elemento com o valor buscado.
int[] dados = { 52, 17, 69, 84, 3, 26, 83, 54, 19, 50 }; int valor_procurado = 54; bool valor_encontrado = false; for (int i = 0; i < dados.Length; i++) { if (dados[i] == valor_procurado) { Console.WriteLine("Valor encontrado no indice " + i); valor_encontrado = true; break; // Encerra o loop, pois já achamos o valor } } if (!valor_encontrado) { Console.WriteLine("Valor não encontrado"); }
Para a Busca Binária funcionar, há uma condição OBRIGATÓRIA: o vetor precisa estar ordenado (do menor para o maior). Se o vetor estiver desordenado, o algoritmo não funcionará e dará resultados incorretos.
Este método usa a estratégia de "divisão e conquista", como ao procurar no dicionário:
int[] dados = { 3, 17, 19, 26, 50, 52, 54, 69, 83, 84 }; // Vetor OBRIGATORIAMENTE ordenado int valor_procurado = 54; bool valor_encontrado = false; int inicio = 0; int fim = dados.Length - 1; int meio; do { meio = inicio + (fim - inicio) / 2; // Calcula o índice do meio if (dados[meio] == valor_procurado) { Console.WriteLine("Valor encontrado no índice " + meio); valor_encontrado = true; break; } else if (dados[meio] > valor_procurado) { fim = meio - 1; // Descarta a segunda metade } else { inicio = meio + 1; // Descarta a primeira metade } } while (inicio <= fim); if (!valor_encontrado) { Console.WriteLine("Valor não encontrado"); }
Como podemos provar que um algoritmo é "melhor" que outro de forma objetiva? Usamos uma ferramenta matemática chamada Notação Grande O (Big O). Ela não mede o tempo em segundos, mas sim como a quantidade de operações (a "demora") de um algoritmo cresce à medida que a quantidade de dados de entrada (que chamamos de 'n') aumenta.
Lê-se "O de n". Isso significa que, no pior caso, o número de passos é diretamente proporcional ao número de elementos (`n`). Se o vetor tem 10 elementos, pode levar até 10 verificações. Se tiver 1 milhão de elementos, pode levar até 1 milhão de verificações. O crescimento é linear.
Lê-se "O de log de n". Esta é a grande vantagem. Significa que o número de passos cresce de forma muito lenta. Mesmo que você dobre o número de elementos, o número de passos no pior caso aumenta em apenas um. Para encontrar um item em um vetor com 1 milhão de elementos, a busca binária leva no máximo 20 passos!
O gráfico abaixo mostra a diferença: a linha da busca linear (função `n`) sobe de forma íngreme e constante, enquanto a linha da busca binária (função `log n`) fica quase plana, mostrando como ela é mais "escalável" para grandes volumes de dados.
Veja o seguinte vídeo para melhor entendimento sobre análise de algoritmos: link
A escolha entre os algoritmos depende do seu problema: