Fundamentos
Busca linear e busca binária em Python
Aprenda a procurar um valor numa lista com a busca linear e com a binária, conte os passos de cada uma e veja usos reais com a ESP32.
Por Prof. Rodrigo Faustino · Atualizado em · 18 min de leitura
Buscar é responder a uma pergunta que todo programa faz o tempo todo: este valor está na lista, e em que posição? Um cartão de acesso está entre os autorizados, um código de aluno existe na turma, a leitura de um sensor já passou do limite. Existem duas formas clássicas de responder, e a diferença entre elas é um bom primeiro contato com a ideia de algoritmo eficiente. A busca linear olha os elementos um a um e funciona em qualquer lista. A busca binária olha o elemento do meio e descarta metade da lista a cada passo, mas só funciona quando a lista está ordenada.
Este artigo escreve as duas à mão, conta quantas comparações cada uma faz, mostra o que acontece quando a binária recebe uma lista fora de ordem, e apresenta três usos na ESP32. Todos os exemplos foram executados no simulador, e os resultados citados são os que ele produz. Uma ressalva já no começo: o módulo bisect do Python de computador, que traz a busca binária pronta, não existe no simulador, e por isso escreveremos a busca nós mesmos, o que de qualquer modo é o exercício que interessa.
Busca linear: um por vez
A ideia é a mais natural possível: começar no primeiro elemento, comparar com o que se procura, e seguir para o próximo até achar ou até a lista acabar. O artigo sobre listas já mostrou o in e o index, e a busca linear é o que eles fazem por baixo. Escrevê-la à mão mostra o raciocínio:
def buscar(lista, alvo):
for i in range(len(lista)):
if lista[i] == alvo:
return i
return -1
nums = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
print(buscar(nums, 23), buscar(nums, 7), buscar(nums, 2), buscar(nums, 91))
print(23 in nums, 7 in nums, nums.index(23), nums.count(5))
def buscar_contando(lista, alvo):
comparacoes = 0
for i in range(len(lista)):
comparacoes += 1
if lista[i] == alvo:
return i, comparacoes
return -1, comparacoes
print(buscar_contando(nums, 23))
print(buscar_contando(nums, 2))
print(buscar_contando(nums, 7))
def todas(lista, alvo):
pos = []
for i, v in enumerate(lista):
if v == alvo:
pos.append(i)
return pos
print(todas([4, 1, 4, 7, 4], 4), todas([4, 1, 4, 7, 4], 9))
alunos = [
{"id": 101, "nome": "Ana"},
{"id": 102, "nome": "Bruno"},
{"id": 103, "nome": "Carla"}
]
def achar_aluno(codigo):
for a in alunos:
if a["id"] == codigo:
return a["nome"]
return None
print(achar_aluno(102), achar_aluno(999))
def primeiro_maior(lista, limite):
for v in lista:
if v > limite:
return v
return None
print(primeiro_maior(nums, 40), primeiro_maior(nums, 100))
maior = nums[0]
for v in nums:
if v > maior:
maior = v
print(maior)
print("fim")A saída é 5 -1 0 9, depois True False 5 1, depois (5, 6), (0, 1) e (-1, 10), depois [0, 2, 4] [], depois Bruno None, depois 56 None, depois 91 e por fim fim.
A função buscar percorre os índices com range(len(lista)) e, ao achar o alvo, devolve a posição com return, o que encerra a função na hora. Se o laço termina sem achar, a execução chega ao return -1 depois dele. O -1 é a convenção para "não achei", a mesma do método find dos textos, porque não é uma posição que alguém procure. Repare no lugar do return -1: ele está fora do laço, alinhado com o for. Esse alinhamento é o detalhe mais importante da função, e voltaremos a ele na seção de erros.
A segunda linha compara com os recursos prontos. O 23 in nums responde só sim ou não, o nums.index(23) devolve a posição, e o nums.count(5) conta quantas vezes o valor aparece. Eles fazem a mesma busca linear sem que você escreva o laço, e são a primeira escolha quando basta saber se um valor existe. A diferença é que o index levanta um erro se o valor não estiver na lista, enquanto a função buscar devolve -1.
Contar as comparações
A função buscar_contando devolve duas coisas, a posição e o número de comparações feitas, com return i, comparacoes, que na verdade é uma tupla, como visto no artigo sobre tuplas e desempacotamento. Os resultados mostram o comportamento da busca linear:
- Achar o
2, que é o primeiro, custa 1 comparação: o melhor caso. - Achar o
23, no meio da lista, custa 6. - Procurar o
7, que não existe, custa 10: o pior caso, em que a lista toda é percorrida para só então dizer que não há.
Uma busca linear numa lista de n elementos faz, no pior caso, n comparações. Para dez elementos, ninguém repara. Para um milhão, é um milhão de comparações a cada busca.
Variações da busca linear
O mesmo esqueleto resolve vários problemas parecidos, e vale reconhecê-lo:
- Todas as posições. A função
todasnão para no primeiro achado. Ela guarda cada posição numa lista comappend, e usa oenumeratepara ter índice e valor. Sem ocorrências, devolve a lista vazia. - Busca em registros. O
achar_alunopercorre uma lista de dicionários e compara um campo, oid. Devolve o nome do aluno ouNone. É o padrão de qualquer "procure o cadastro com este código", e o artigo sobre dicionários mostrou como montar esses registros. - O primeiro que passa de um limite. O
primeiro_maiordevolve o valor, e não a posição, do primeiro elemento acima do limite. - O maior valor. Procurar o maior elemento também é uma busca linear: guarda-se o melhor visto até agora e atualiza-se quando aparece um maior. É o que os desafios Maior da Lista e Maior Número pedem, e o desafio Busca na Lista pede a busca de um valor lido do teclado.
A IA que lembra da sua vida e mora no seu computador
- Memória de longo prazo com a fonte de cada resposta
- Funciona offline: seus dados ficam no seu PC
- Lê PDFs, slides, fotos e gravações de reunião
Plano Essencial grátis para sempre
Busca binária: olhar o meio
Pense num dicionário de papel. Para achar uma palavra, ninguém começa na primeira página. Abre-se no meio, vê-se se a palavra procurada vem antes ou depois, e repete-se a ideia na metade certa. A busca binária faz exatamente isso, e só dá certo porque o dicionário está em ordem alfabética: sem ordem, olhar o meio não diz nada sobre onde está o resto.
def busca_binaria(lista, alvo):
esq = 0
dir = len(lista) - 1
while esq <= dir:
meio = (esq + dir) // 2
if lista[meio] == alvo:
return meio
elif lista[meio] < alvo:
esq = meio + 1
else:
dir = meio - 1
return -1
nums = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
print(busca_binaria(nums, 23), busca_binaria(nums, 7), busca_binaria(nums, 2), busca_binaria(nums, 91))
print(busca_binaria([], 5), busca_binaria([5], 5), busca_binaria([5], 6))
def busca_binaria_passos(lista, alvo):
esq = 0
dir = len(lista) - 1
passo = 0
while esq <= dir:
meio = (esq + dir) // 2
passo += 1
print("passo", passo, "esq", esq, "dir", dir, "meio", meio, "valor", lista[meio])
if lista[meio] == alvo:
return meio
elif lista[meio] < alvo:
esq = meio + 1
else:
dir = meio - 1
return -1
print(busca_binaria_passos(nums, 23))
print(busca_binaria_passos(nums, 7))
print("fim")A saída começa com 5 -1 0 9 e -1 0 -1. Depois vem o rastro da busca pelo 23: passo 1 esq 0 dir 9 meio 4 valor 16, passo 2 esq 5 dir 9 meio 7 valor 56, passo 3 esq 5 dir 6 meio 5 valor 23 e o resultado 5. Em seguida, o rastro da busca pelo 7: passo 1 esq 0 dir 9 meio 4 valor 16, passo 2 esq 0 dir 3 meio 1 valor 5, passo 3 esq 2 dir 3 meio 2 valor 8 e o resultado -1. Por fim, fim.
O algoritmo mantém dois marcadores, esq e dir, que delimitam a faixa onde o alvo ainda pode estar. No começo, a faixa é a lista inteira, da posição 0 até a última. A cada volta do laço:
- Calcula-se o
meioda faixa, com a divisão inteira(esq + dir) // 2. - Se o valor do meio é o alvo, a busca acabou: devolve-se
meio. - Se o valor do meio é menor que o alvo, o alvo só pode estar à direita, e a faixa passa a começar em
meio + 1. - Se é maior, o alvo só pode estar à esquerda, e a faixa passa a terminar em
meio - 1.
O laço roda enquanto a faixa tiver pelo menos uma posição, esq <= dir. Quando esq passa de dir, a faixa ficou vazia e o alvo não está na lista, o que leva ao return -1. O rastro do passo mostra isso nos dois casos. Para o 23, a faixa vai de 10 posições para 5, depois para 2, e no terceiro passo o meio já é o alvo. Para o 7, que não existe, a faixa encolhe até esvaziar, e a busca conclui "não está" em três passos, enquanto a linear precisou de dez.
Os dois casos de borda aparecem na segunda linha da saída. Com a lista vazia, dir começa em -1, o laço nem roda e o resultado é -1. Com um elemento só, o meio é o próprio elemento. O -1 0 -1 mostra a lista vazia, o achado e o não achado.
O meio + 1 e o meio - 1 merecem atenção. Eles descartam o próprio meio, que já foi comparado. Se algum dos dois fosse escrito só como meio, a faixa poderia deixar de encolher, e o laço rodaria para sempre. É o tipo de erro que se descobre com um print do rastro, como o da função busca_binaria_passos.
Quanto trabalho cada busca dá
A vantagem da binária está no ritmo em que o trabalho cresce. A cada passo, a faixa cai pela metade, e então o número de passos no pior caso é quantas vezes é possível dividir a lista ao meio até sobrar nada. O código abaixo conta isso sem precisar criar listas enormes, simulando só os marcadores:
def passos_pior_caso(n):
esq = 0
dir = n - 1
passos = 0
while esq <= dir:
meio = (esq + dir) // 2
passos += 1
esq = meio + 1
return passos
for n in [10, 100, 1000, 1000000]:
print(n, passos_pior_caso(n))
print(passos_pior_caso(0), passos_pior_caso(1), passos_pior_caso(2), passos_pior_caso(3), passos_pior_caso(4))
print("fim")A saída é 10 4, 100 7, 1000 10, 1000000 20, depois 0 1 2 2 3 e por fim fim.
Para uma lista de 1000 elementos, a binária faz no máximo 10 comparações, e a linear, 1000. Para um milhão, são 20 contra um milhão. Cada vez que a lista dobra de tamanho, a binária faz um passo a mais, enquanto a linear faz o dobro de passos. Esse jeito de medir como o trabalho cresce com o tamanho dos dados é o assunto do último artigo desta parte, sobre complexidade de algoritmos, e aqui basta guardar a imagem: uma cresce em linha reta, a outra quase não se mexe.
A conta tem um preço. A binária só vale com a lista ordenada, e ordenar custa trabalho. Se a lista muda toda hora, ou se só se faz uma busca nela, ordenar antes para buscar depois sai mais caro do que uma busca linear simples. A binária compensa quando a lista é grande e ordenada uma vez, e as buscas são muitas. Os próximos artigos mostram como ordenar.
O que dá errado com a busca binária
A busca binária tem pré-requisitos que ela não verifica. O mais importante é a ordem:
def busca_binaria(lista, alvo):
esq = 0
dir = len(lista) - 1
while esq <= dir:
meio = (esq + dir) // 2
if lista[meio] == alvo:
return meio
elif lista[meio] < alvo:
esq = meio + 1
else:
dir = meio - 1
return -1
desordenada = [9, 2, 7, 1, 5, 3]
print(busca_binaria(desordenada, 5), 5 in desordenada)
print(busca_binaria(desordenada, 9), 9 in desordenada)
print(busca_binaria(desordenada, 2), 2 in desordenada)
print(busca_binaria(sorted(desordenada), 5))
print(busca_binaria([1, 2, 2, 2, 3], 2), busca_binaria([1, 2, 2, 2, 2, 3], 2))
print(busca_binaria(["ana", "bia", "caio", "dora"], "caio"))
print("fim")A saída é -1 True, -1 True, -1 True, depois 3, depois 2 2, depois 2 e por fim fim.
Os três primeiros resultados são o problema. Os valores 5, 9 e 2 estão na lista, como o in confirma com True, mas a busca binária disse -1 para os três. Ela olhou o meio, concluiu algo sobre a ordem que não existe, e foi procurar do lado errado. Não houve erro nem aviso: o programa só respondeu errado. Depois de passar a lista por sorted, a busca acha o 5 na posição 3 da lista ordenada, [1, 2, 3, 5, 7, 9].
O quinto resultado mostra o comportamento com valores repetidos. Nas listas [1, 2, 2, 2, 3] e [1, 2, 2, 2, 2, 3], a busca devolve a posição 2 nas duas, que é uma posição onde há um 2, mas não a primeira. A busca binária devolve uma das ocorrências, a que caiu no meio, e não garante a primeira nem a última. Se o problema pede a primeira, é preciso ajustar o algoritmo, ou usar a busca linear.
O último resultado mostra que a busca binária também funciona com textos, porque o < compara textos em ordem alfabética, como visto no artigo sobre strings. O requisito é que a lista esteja ordenada pelo mesmo critério da comparação.
Da ementa ao semestre planejado
- Plano de ensino e calendário montados sozinhos
- Diário de aulas pronto para colar no SIGA
- Slides e listas de exercícios com gabarito
Versão Community grátis · Windows
Na ESP32: tabela de calibração, cartões e limites
from machine import ADC, Pin
TABELA = [(0, -10), (500, 0), (1200, 10), (2000, 20), (2800, 30), (3500, 40), (4095, 50)]
def faixa(leitura):
esq = 0
dir = len(TABELA) - 1
while esq < dir:
meio = (esq + dir + 1) // 2
if TABELA[meio][0] <= leitura:
esq = meio
else:
dir = meio - 1
return esq
for lido in [0, 499, 500, 1500, 3499, 4095]:
i = faixa(lido)
print(lido, i, TABELA[i][1])
CARTOES = ["A1B2", "C3D4", "E5F6"]
for lido in ["C3D4", "ZZZZ"]:
print(lido, "liberado" if lido in CARTOES else "negado")
leituras = [310, 295, 402, 515, 530, 498]
limite = 500
for i in range(len(leituras)):
if leituras[i] > limite:
print("primeira acima do limite:", i, leituras[i])
break
else:
print("nenhuma acima")
adc = ADC(Pin(34))
adc.atten(ADC.ATTN_11DB)
print(0 <= adc.read() <= 4095)
print("fim")A saída é 0 0 -10, 499 0 -10, 500 1 0, 1500 2 10, 3499 4 30, 4095 6 50, depois C3D4 liberado e ZZZZ negado, depois primeira acima do limite: 3 515, depois True e fim.
O primeiro uso é uma tabela de calibração. A leitura do conversor analógico, de 0 a 4095, é convertida em temperatura por uma tabela de faixas, em que cada linha diz "a partir deste valor lido, vale esta temperatura". Os números do exemplo são inventados para ilustrar, e uma curva de verdade vem do manual do sensor ou de medições. O artigo sobre o ADC da ESP32 mostra por que a leitura não é linear.
A tabela está ordenada pela leitura, então a busca binária cabe. Só que aqui o objetivo é diferente: não se procura um valor exato, e sim a última faixa que começa antes da leitura. Por isso a função faixa muda dois detalhes: o meio é calculado com (esq + dir + 1) // 2, arredondando para cima, e o laço roda com esq < dir, sem o teste de igualdade. Quando a faixa do meio começa em um valor menor ou igual à leitura, esq passa a ser o próprio meio, que ainda pode ser a resposta. O + 1 no cálculo do meio garante que a faixa sempre encolhe. Com 7 linhas, a diferença entre as duas buscas é de poucos passos, e uma busca linear daria o mesmo resultado, mas em tabelas com centenas de linhas a binária compensa.
O segundo uso é a lista de cartões autorizados. Aqui o in resolve: a lista é curta, não está ordenada e muda quando alguém é cadastrado. Ordenar e usar a binária seria mais trabalho sem ganho. O exemplo só ilustra a busca; um controle de acesso de verdade pede muito mais cuidado, como guardar os códigos fora do programa.
O terceiro é achar o primeiro valor acima de um limite numa sequência de leituras. O laço para com break na primeira ocorrência, e o else do for, visto no artigo sobre break, continue e else, só roda quando o laço termina sem break, ou seja, quando nenhuma leitura passou do limite. As leituras chegam em ordem de tempo e não de valor, então só a linear faz sentido.
Por fim, as duas últimas linhas criam um ADC no pino 34 e confirmam que a leitura fica entre 0 e 4095. Elas não fazem parte da busca: mostram de onde viria o lido num circuito real.
Erros comuns
O primeiro erro é usar o index esperando um -1:
nums = [2, 5, 8]
print(nums.index(7))ValueError: object not in sequenceNo Python de computador, a mensagem é 7 is not in list. O index exige que o valor exista. A solução é testar antes com in, ou escrever a função buscar, que devolve -1. O erro é o mesmo quando se passa um ponto de partida que fica depois da única ocorrência.
O segundo é importar o bisect, que existe no Python de computador:
import bisect
print(bisect.bisect_left([1, 3, 5], 3))ImportError: no module named 'bisect'O simulador não tem esse módulo, e não se deve contar com ele na placa. A saída é escrever a busca à mão, como neste artigo.
O terceiro é comparar tipos diferentes na busca binária, como procurar o texto "3" numa lista de números:
def busca_binaria(lista, alvo):
esq = 0
dir = len(lista) - 1
while esq <= dir:
meio = (esq + dir) // 2
if lista[meio] == alvo:
return meio
elif lista[meio] < alvo:
esq = meio + 1
else:
dir = meio - 1
return -1
print(busca_binaria([1, 3, 5], "3"))TypeError: unsupported types for __lt__: 'int', 'str'No Python de computador, o texto é '<' not supported between instances of 'int' and 'str'. A comparação de igualdade, ==, aceita tipos diferentes e só dá falso, mas o < não. Isso costuma acontecer quando o alvo vem de input(), que sempre devolve texto, e a lista tem números. A correção é converter o alvo com int().
O quarto é um erro de cálculo do meio com a divisão comum:
nums = [2, 5, 8, 12]
meio = (0 + 3) / 2
print(meio)
print(nums[meio])1.5
TypeError: list indices must be integers, not floatO / devolve um número com vírgula, e a lista só aceita índice inteiro. É por isso que a busca usa o //. No Python de computador, a mensagem é list indices must be integers or slices, not float.
Armadilhas silenciosas
Alguns erros não geram mensagem nenhuma. O pior deles na busca linear é o return -1 no lugar errado:
def errada(lista, alvo):
for i in range(len(lista)):
if lista[i] == alvo:
return i
else:
return -1
print(errada([5, 6, 7], 5), errada([5, 6, 7], 7))
def ok(lista, alvo):
for i in range(len(lista)):
if lista[i] == alvo:
return i
return -1
print(ok([5, 6, 7], 5), ok([5, 6, 7], 7))
print("fim")A saída é 0 -1 e 0 2, e depois fim. A função errada devolve -1 logo no primeiro elemento que não for o alvo, e nunca olha os outros. Para o 5, que é o primeiro, dá certo, e é por isso que o teste simples passa. Para o 7, no fim da lista, dá -1, e o valor estava lá. O else colado ao if dentro do laço decide cedo demais. A regra é: só se pode dizer "não achei" depois de olhar todos, e isso é o que o return -1 fora do laço faz.
O outro é usar o resultado -1 como se fosse uma posição. Em Python, o índice -1 é válido, e é o último elemento. Com a lista nums de antes, nums[buscar(nums, 7)] dá 91, e não um erro. A busca disse "não achei", o programa ignorou e pegou o último elemento. Sempre se confere o resultado antes de usá-lo como índice.
Há ainda o laço da busca binária que perde o último candidato. Se a condição for esq < dir em vez de esq <= dir, a faixa de um elemento só nunca é examinada. Numa execução com essa troca, a busca devolve -1 para o 5 em [5], -1 para o 8 em [2, 5, 8] e -1 para o 12 em [2, 5, 8, 12], e só acerta o 5 em [2, 5, 8], onde o meio cai no valor certo. Quem testa só com o elemento do meio não vê o defeito.
O que costuma aparecer em sala
Estes são padrões que se repetem com quem aprende busca. Não são o relato de uma turma específica.
O return -1 dentro do laço. É o mais comum, como mostrado. A função passa no teste de achar o primeiro elemento e falha nos outros. O caminho de volta é testar sempre com o último elemento e com um valor que não existe.
Devolver o valor em vez da posição. Escrever return lista[i] ou return v onde se pedia a posição. Como a busca compara lista[i] com o alvo, o valor devolvido é igual ao alvo, e a resposta não diz nada de novo.
Usar o -1 como índice. Já descrito. A pessoa busca, guarda o resultado e acessa a lista sem verificar.
Busca binária em lista não ordenada. O resultado vem errado sem aviso, e a pessoa conclui que o algoritmo "não funciona". O hábito a criar é perguntar, antes de qualquer busca binária, quem garante a ordem.
Confundir a binária com "pular de dois em dois". Alguns imaginam que ela olha uma posição sim, outra não. Rodar a função com o rastro de passos, que imprime esq, dir e meio, resolve a dúvida melhor do que a explicação.
/ no lugar de //. Gera o erro de índice com número com vírgula, e quase sempre se resolve de primeira.
meio em vez de meio + 1. Em alguns casos o programa trava num laço que não termina. Colocar um contador de passos que interrompe o laço depois de, digamos, 50 voltas é uma boa rede de proteção durante os testes.
Só testar com o valor que existe. Os três testes mínimos são: um valor no começo, um no fim e um que não existe. Com isso, a maioria dos defeitos aparece.
Exercício: busca binária com contagem de passos
Escreva um programa que leia a quantidade n de elementos, depois n números já em ordem crescente, e por fim o valor a procurar. Ele deve mostrar a posição achada e em quantos passos, ou que o valor não foi encontrado, e comparar com a busca linear feita pelos recursos prontos. O bloco usa entradas= para fornecer a lista [3, 7, 11, 15, 19] e o alvo 15.
n = int(input())
lista = []
for i in range(n):
lista.append(int(input()))
alvo = int(input())
esq = 0
dir = n - 1
passos = 0
achou = -1
while esq <= dir:
meio = (esq + dir) // 2
passos += 1
if lista[meio] == alvo:
achou = meio
break
elif lista[meio] < alvo:
esq = meio + 1
else:
dir = meio - 1
if achou == -1:
print("nao encontrado em", passos, "passos")
else:
print("posicao", achou, "em", passos, "passos")
print("busca linear:", lista.index(alvo) if alvo in lista else -1)
print("fim")O simulador repete na saída os valores digitados, um por linha, e depois vêm posicao 3 em 2 passos, busca linear: 3 e fim.
Na primeira volta, o meio é a posição 2, que vale 11 e é menor que 15, então a faixa passa a começar na posição 3. Na segunda, o meio é a posição 3, que vale 15, e a busca acaba. O break sai do laço assim que o valor é achado, e a variável achou guarda a posição, com -1 como valor inicial de "ainda não achei". A última linha usa o index guardado por um in, para nunca levantar o ValueError.
Para treinar além disso, tente: procurar um valor que não existe, como 10, e ver quantos passos a binária gasta; procurar o primeiro e o último elemento; acrescentar uma verificação de que a lista lida está mesmo em ordem, com um laço que compare cada elemento com o seguinte; e mostrar, junto, quantas comparações a busca linear teria feito.
Perguntas frequentes
Qual busca devo usar? Se a lista é pequena, não está ordenada, ou muda toda hora, use a linear, ou simplesmente o in e o index. Se a lista é grande, está ordenada e recebe muitas buscas, a binária compensa.
Preciso escrever a busca linear à mão se existe o in? Para saber só se o valor existe, o in basta. Escrever à mão é necessário quando a busca tem uma regra própria, como achar o primeiro valor acima de um limite, comparar um campo de um registro, ou contar as comparações.
A busca binária funciona em lista de textos? Funciona, desde que a lista esteja ordenada em ordem alfabética e o alvo seja um texto. O resultado depende da comparação de caracteres, e por isso letras maiúsculas e minúsculas se ordenam separadas.
O que faço se a lista tem valores repetidos? A busca binária devolve uma das posições, sem garantia de qual. Para achar a primeira, ajuste o algoritmo para continuar procurando à esquerda depois de um achado, ou use a busca linear.
Por que o simulador não tem bisect? Porque ele não existe no simulador, que imita o MicroPython. A busca escrita à mão é curta e serve nos dois lugares, no computador e na placa.
A busca binária pode ser escrita com recursão? Pode: a função chama a si mesma com uma faixa menor. Como a faixa cai pela metade, a profundidade fica pequena. O artigo sobre recursividade trata do assunto.
Para continuar
O desafio Busca na Lista pratica a busca linear com um valor lido do teclado, e os desafios Maior da Lista e Maior Número praticam a varredura que guarda o melhor valor visto. Para rever a base, vale passar pelos artigos sobre listas, operações com listas e matrizes, e pela trilha de lógica.
O próximo artigo trata da ordenação: o bubble sort e o selection sort, dois algoritmos simples que colocam uma lista em ordem, explicados passo a passo.