Estes slides constituem um roteiro prático para entender, comparar e experimentar a busca sequencial e a busca binária, com ênfase em:
Suponha que você tenha uma lista de valores representando:
Pergunta central:
Dado um valor
x, ele está na lista?
Se sim, em qual posição?
Quando não sabemos nada sobre a ordem dos elementos (lista não ordenada):
x, paramos e retornamos a posição;Portanto, a busca sequencial é um algoritmo (O(n)).
E se a lista já estiver ordenada?
Nesses casos, podemos usar uma estratégia bem mais rápida:
A busca binária explora o fato de que a coleção está ordenada para eliminar metade dos elementos a cada passo.
Queremos encontrar a palavra “limão” em um dicionário:
A cada passo, metade das possibilidades é descartada.
Para usar a busca binária corretamente, é obrigatório:
<, >, ==);Se a lista não estiver ordenada, a busca binária:
BUSCA-BINÁRIA (V[], início, fim, e)
i recebe o índice do meio entre início e fim
se (V[i] = e) então
devolva o índice i # elemento e encontrado
fimse
se (início = fim) então
não encontrou o elemento procurado
senão
se (V[i] vem antes de e) então
BUSCA-BINÁRIA(V, i+1, fim, e)
senão
BUSCA-BINÁRIA(V, início, i-1, e)
fimse
fimsepublic static int buscaBinaria(int[] array, int valor) {
int inicio = 0;
int fim = array.length - 1;
while (inicio <= fim) {
int meio = (inicio + fim) / 2;
if (array[meio] == valor) {
return meio; // encontrou
}
if (valor > array[meio]) {
inicio = meio + 1; // procura na metade direita
} else {
fim = meio - 1; // procura na metade esquerda
}
}
return -1; // não encontrou
}public static int buscaBinariaRecursiva(int[] vetor,
int valorBuscado,
int inicio,
int fim) {
if (inicio > fim) {
return -1; // intervalo vazio, não encontrou
}
int meio = (inicio + fim) / 2;
if (valorBuscado == vetor[meio]) {
return meio;
} else if (valorBuscado < vetor[meio]) {
return buscaBinariaRecursiva(vetor, valorBuscado, inicio, meio - 1);
} else {
return buscaBinariaRecursiva(vetor, valorBuscado, meio + 1, fim);
}
}function buscaBinaria(umVetor, item) {
let prim = 0;
let ult = umVetor.length - 1;
let achou = false;
while (prim <= ult && !achou) {
let meioLista = Math.floor((prim + ult) / 2);
if (umVetor[meioLista] === item) {
achou = true;
} else if (item < umVetor[meioLista]) {
ult = meioLista - 1;
} else {
prim = meioLista + 1;
}
}
return achou;
}Em cada iteração:
Portanto, o número de passos necessários é da ordem de:
A busca binária é, portanto, um algoritmo de complexidade ((n)).
Considere o vetor ordenado:
V = [-2, 0, 4, 7, 8, 9, 11]Objetivo: buscar o valor 7.
inicio = 0, fim = 6meio = 3 ⇒ V[3] = 7Agora, buscar o valor 5 no mesmo vetor:
inicio = 0, fim = 6meio = 3 ⇒ V[3] = 75 < 7 ⇒ novo intervalo: inicio = 0, fim = 2meio = 1 ⇒ V[1] = 05 > 0 ⇒ novo intervalo: inicio = 2, fim = 2meio = 2 ⇒ V[2] = 45 > 4 ⇒ novo intervalo: inicio = 3, fim = 2 (intervalo vazio)Conclusão: 5 não está no vetor.
Considere o seguinte problema:
x está no vetor?”;x, devemos imprimir:
n).Perguntas:
Arrays.sort em Java);Suponha:
(n = 10^5) e (m = 10^5).
Busca Linear:
Busca Binária:
Moral da história: para muitas buscas em vetores grandes, a busca binária é extremamente vantajosa.
Implemente em Java (ou outra linguagem que preferir):
N;m valores a serem buscados;Sugestão de código para comparação de tempos em Java:
int N = 100000;
int M = 100000;
int[] vetor = new int[N];
for (int i = 0; i < N; i++) {
vetor[i] = i * 2;
}
int[] consultas = new int[M];
Random rand = new Random();
for (int i = 0; i < M; i++) {
consultas[i] = rand.nextInt(2 * N);
}
long t1 = System.currentTimeMillis();
for (int x : consultas) {
// chamada da busca linear
}
long tempoLinear = System.currentTimeMillis() - t1;
long t2 = System.currentTimeMillis();
for (int x : consultas) {
// chamada da busca binária
}
long tempoBinaria = System.currentTimeMillis() - t2;
System.out.println("Linear: " + tempoLinear + " ms");
System.out.println("Binária: " + tempoBinaria + " ms");Alguns problemas típicos em implementações de busca binária:
meio (por exemplo, não atualizar corretamente inicio e fim);Recomendação:
Implemente um programa que:
n e m;n inteiros distintos;m inteiros (consultas);n) ou -1 caso não encontre.Tente primeiro usando busca linear, depois substitua pela busca binária e compare o desempenho.
Pergunta final:
Em quais outros problemas você consegue imaginar que eliminar metade das possibilidades a cada passo seria uma boa estratégia?
Na próxima prática, vamos usar esse conhecimento como base para outros algoritmos de busca e ordenação.