Algoritmos de busca e ordenação e sua eficiência

Aprenda como os computadores encontram e ordenam dados e como distinguir um método rápido de um lento. Rastreie a busca linear e a busca binária e três algoritmos clássicos de ordenação, por bolha, por seleção e por intercalação, em listas reais. Conte os passos de cada um, veja como essas contagens crescem com os dados e preveja tempos de execução. Depois, justifique que um algoritmo sempre dá a resposta correta, teste-o com casos-limite e escolha o algoritmo adequado à situação.

BásicoAula 4 de 7 do curso Curso de Introdução à ciência da computação

O que você vai aprender

  1. Encontrar um valor procurado em uma lista usando busca linear e, quando a lista estiver ordenada, busca binária. Rastrear cada método em listas reais e contar quantos elementos ele verifica.
    • Buscar em qualquer lista usando busca linear
      Verificar os elementos um a um desde o início, retornar a posição da primeira correspondência ou informar que o valor procurado está ausente e contar as comparações no melhor e no pior caso.
    • Buscar em uma lista ordenada usando busca binária
      Usar a ordem da lista para reduzir pela metade a parte ainda em análise a cada verificação, rastrear as posições inferior, superior e central e explicar por que cerca de log₂ n verificações são suficientes.
  2. Explicar o que uma ordenação correta deve produzir, rastrear a ordenação por bolha e por seleção passada a passada e contar suas comparações e trocas.
    • Descrever as características de uma lista corretamente ordenada
      Definir ordem, chaves de ordenação, trocas, estabilidade, ordenação no próprio local e inversões, para que algoritmos de ordenação possam ser rastreados, verificados e comparados.
    • Rastrear e contar as operações da ordenação por bolha
      Ordenar uma lista trocando repetidamente elementos vizinhos que estão fora de ordem, acompanhar cada passada, parar antecipadamente quando uma passada não fizer trocas e contar as comparações e trocas.
    • Rastrear e contar as operações da ordenação por seleção
      Ordenar uma lista selecionando repetidamente o menor elemento restante e trocando-o para sua posição, acompanhar cada passada e comparar suas contagens de comparações e trocas com as da ordenação por bolha.
  3. Intercalar duas listas ordenadas em uma só, rastrear a ordenação por intercalação enquanto ela divide uma lista e intercala as partes novamente e explicar por que precisa de cerca de n log₂ n comparações.
    • Intercalar duas listas ordenadas em uma só
      Combinar duas listas já ordenadas escolhendo repetidamente o menor elemento à frente, contar as comparações e explicar por que o resultado está ordenado.
    • Rastrear a ordenação por intercalação e explicar seu crescimento n log n
      Ordenar dividindo uma lista em metades até restarem elementos individuais e intercalando as partes novamente em ordem, usando um caso base para interromper a divisão e contando as comparações em cada nível.
  4. Contar os passos básicos de um algoritmo em função do tamanho da entrada, comparar os crescimentos logarítmico, linear, n log n e quadrático e usar taxas de crescimento para prever tempos de execução.
    • Contar os passos executados por um algoritmo
      Medir um algoritmo pelo número de operações básicas que ele executa para uma entrada de tamanho n, encontrar a contagem para laços e laços aninhados e distinguir o melhor, o pior e o caso médio.
    • Comparar como a quantidade de passos cresce com o tamanho da entrada
      Reconhecer crescimentos constante, logarítmico, linear, n log n, quadrático e exponencial, ver o que acontece quando a entrada dobra, ler a notação O informal e explicar por que a taxa de crescimento importa mais que fatores constantes para entradas grandes.
    • Prever e medir tempos de execução
      Usar um tempo de execução conhecido e uma taxa de crescimento para estimar o tempo para uma entrada maior, verificar uma taxa de crescimento medindo o tempo de um programa com tamanhos que dobram e apresentar previsões como estimativas.
  5. Mostrar que um algoritmo termina e dá a resposta correta para toda entrada válida, testá-lo com casos-limite e avaliar tempo, memória e outros compromissos entre critérios para escolher um algoritmo adequado à situação.
    • Justificar que um algoritmo está correto
      Definir o que um algoritmo deve alcançar, explicar por que apenas os testes não podem provar sua correção e usar invariantes de laço e um argumento de terminação para mostrar que algoritmos de busca e ordenação funcionam.
    • Testar algoritmos com casos-limite
      Escolher entradas nos limites do que um algoritmo processa, prever a saída esperada antes da execução e encontrar os erros de uma unidade e laços infinitos que entradas comuns não revelam.
    • Escolher um algoritmo adequado à situação
      Comparar algoritmos de busca e ordenação quanto ao tempo, à memória, à estabilidade e aos requisitos dos dados e decidir qual é adequado a uma tarefa, incluindo quando compensa ordenar primeiro.

Guia de estudo de Algoritmos de busca e ordenação

5 capítulos

1

Buscar em uma lista passo a passo

Encontrar um valor começa com uma pergunta simples: quais posições ainda precisam ser verificadas? Acompanhe a busca linear em uma lista comum e depois use a ordem para eliminar grandes partes de uma lista com a busca binária. Você acompanhará posições e valores separadamente, verá como cada busca informa uma falha e contará o trabalho necessário para entradas fáceis e difíceis. Rastreamentos curtos também mostram por que a última posição restante ainda precisa ser verificada.

1.1 Buscar em qualquer lista usando busca linear

Uma busca verifica se um valor procurado aparece e onde ele aparece. Uma lista tem posições numeradas chamadas índices. Python conta a partir de zero: em [7, 3, 9, 3, 5], o índice 0 contém 7 e o índice 4 contém 5. O valor e seu índice respondem a perguntas diferentes.

Verifique um elemento por vez

A busca linear, também chamada de busca sequencial, começa no primeiro elemento e compara cada elemento com o valor procurado. Ela retorna imediatamente quando encontra uma correspondência. Se a lista terminar sem uma correspondência, retorna -1, nosso sinal para “não encontrado”.

def linear_search(items, target):
    for i in range(len(items)):
        if items[i] == target:
            return i
    return -1

len(items) fornece o número de elementos. range(len(items)) fornece todos os índices válidos, começando em 0 e terminando logo antes do comprimento. items[i] lê o valor no índice atual. Um return encerra a função, portanto uma correspondência posterior nunca substitui a primeira.

A busca por 3 na lista acima ocorre da seguinte forma:

  1. No índice 0, compare 7 com 3. São diferentes, então continue.
  2. No índice 1, compare 3 com 3. São iguais, então retorne o índice 1.

O resultado é o índice 1 após duas comparações. O segundo 3, no índice 3, nunca é verificado. Buscar 4 verifica 7, 3, 9, 3 e 5 e depois retorna -1 após cinco comparações. Um índice retornado igual a 1 indica o segundo elemento, não um elemento cujo valor é 1.

Conte o trabalho

Seja n o número de elementos. Para uma lista não vazia, o melhor caso é uma comparação: o primeiro elemento corresponde ao valor procurado. O pior caso são n comparações: o valor procurado está no fim ou ausente. Uma lista vazia precisa de zero comparações e retorna -1.

Se um valor procurado aparece uma vez e tem a mesma probabilidade de ocupar qualquer posição, sua contagem média de comparações é

1+2+⋯+nn=n+12.

Para 1.000 elementos, são 500,5 comparações. Uma média pode ser fracionária mesmo que cada busca individual faça um número inteiro de comparações. Essa média descreve essa distribuição específica de buscas bem-sucedidas; buscas sem sucesso frequentes aumentariam a média geral.

Coloque o retorno de falha após o laço

Um else: return -1 dentro do laço desistiria na primeira não correspondência. Em [7, 3, 9], rejeitaria uma busca por 3 depois de ver apenas 7. O retorno de falha deve ficar após o laço, quando todas as posições tiverem sido descartadas.

A busca linear não precisa de ordem nem de preparação. Ela funciona com números, palavras ou registros comparados por um identificador. Uma versão projetada para dados ordenados pode parar quando passa pela posição possível do valor procurado: em [2, 5, 8, 12], ver 8 basta para descartar 6. O código acima continua deliberadamente a busca até encontrar uma correspondência ou chegar ao fim.

Tarefas relacionadas usam a mesma varredura, mas com uma regra de parada diferente. Contar todas as ocorrências, coletar todos os índices correspondentes e encontrar o maior elemento exigem inspecionar a lista inteira; encontrar a primeira correspondência permite um retorno antecipado.

Principais conclusões

  • A busca linear verifica as posições em ordem e retorna o primeiro índice correspondente.
  • Retorne -1 somente depois que todas as correspondências possíveis tiverem sido descartadas.
  • Uma lista não vazia precisa de uma comparação no melhor caso e n no pior.
  • A média (n+1)/2 pressupõe uma ocorrência do valor procurado com a mesma probabilidade em cada posição.

1.2 Buscar em uma lista ordenada usando busca binária

A busca binária usa a ordem para descartar posições sem verificá-las individualmente. Sua entrada deve estar em ordem crescente. Ela também precisa de acesso rápido a um elemento em um índice escolhido, como um array ou uma lista Python oferece.

Mantenha um intervalo inclusivo

low e high marcam a primeira e a última posições ainda possíveis, incluindo os dois extremos. Comece com low = 0 e high = len(items) - 1. Escolha o índice central arredondando para baixo. Se o valor central for pequeno demais, todos os valores à sua esquerda também serão pequenos demais; mova low para depois do centro. Se for grande demais, mova high para imediatamente antes dele.

def binary_search(items, target):
    low = 0
    high = len(items) - 1
    while low <= high:
        mid = (low + high) // 2
        if items[mid] == target:
            return mid
        elif items[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return -1

// divide e arredonda para baixo. O laço inclui o caso low == high porque resta uma posição não verificada. Quando low > high, o intervalo está vazio.

Rastreie uma busca com sucesso e outra sem sucesso

Use [3, 8, 12, 17, 23, 31, 42, 56, 64, 77, 85], com índices de 0 a 10. Para encontrar 64, o primeiro índice central é 5, que contém 31. Como 31 é pequeno demais, defina low = 6. O próximo índice central é 8, que contém 64. Retorne 8 após duas verificações de elementos centrais.

Para buscar 20 na mesma lista:

VerificaçãolowhighmidValor centralAtualização
1010531high passa a 4
204212low passa a 3
334317low passa a 4
444423high passa a 3

Agora o intervalo está vazio, então retorne -1. Essa falha é justificada: a ordem da lista justificou cada parte descartada.

Por que é rápida

Cada verificação sem sucesso deixa no máximo metade do intervalo. Para uma lista não vazia, o número máximo de verificações de elementos centrais é ⌊log⁡2n⌋+1. O logaritmo de base 2 descreve divisões sucessivas pela metade: 210=1.024, então mil elementos precisam de no máximo 10 verificações; um milhão precisa de no máximo 20. Uma verificação nesse código Python pode fazer duas comparações, == e <. Verificações e comparações são unidades de contagem diferentes.

Condições e erros nos limites

A ordem é essencial. Ao buscar 2 em [9, 2, 7, 4, 1], a busca vê primeiro 7 e descarta a parte direita, depois vê 9 e descarta a correspondência restante no índice 1. O acesso rápido ao meio também importa: seguir enlaces para alcançar o meio de uma lista encadeada elimina a vantagem de velocidade da versão com array.

Sempre exclua o elemento central testado após uma não correspondência. Usar low = mid pode deixar [10, 20] inalterada para sempre ao buscar 20. Usar while low < high ignora o último candidato e falha ao buscar 5 em [5]. Em uma lista vazia, high = -1, portanto o laço correto nunca começa.

Com duplicatas, esta versão retorna qualquer índice correspondente. Buscar 4 em [2, 4, 4, 4, 9] retorna imediatamente o índice 2; encontrar a primeira ocorrência exige uma busca modificada que continue para a esquerda após uma correspondência.

Principais conclusões

  • A busca binária exige dados ordenados e acesso rápido às posições.
  • Acompanhe um intervalo inclusivo e continue enquanto low <= high.
  • Após uma não correspondência, exclua mid com mid + 1 ou mid - 1.
  • O máximo é ⌊log⁡2n⌋+1 verificações de elementos centrais para n>0.
  • Um índice correspondente não precisa ser o da primeira ocorrência.
  • Um intervalo vazio significa que o valor procurado está ausente.
2

Ordenar uma lista por bolha e por seleção

Uma lista pode parecer ordenada e ainda assim conter os elementos errados. Comece definindo com precisão a tarefa de ordenação, incluindo chaves repetidas e os registros associados a elas. Depois, acompanhe dois métodos que constroem a ordem por meio de trocas: a ordenação por bolha posiciona o maior elemento restante à direita, enquanto a ordenação por seleção posiciona o menor elemento restante à esquerda. Seus rastreamentos revelam custos diferentes de comparação e movimentação.

2.1 Descrever as características de uma lista corretamente ordenada

A ordenação reorganiza elementos por uma chave escolhida. Para números em ordem crescente, cada elemento é menor ou igual ao seguinte. “Não decrescente” permite vizinhos iguais: [2, 5, 5, 9] está ordenada. A ordem decrescente inverte a direção.

Verifique duas condições

Uma ordenação correta deve produzir uma saída em ordem que contenha exatamente os elementos originais, com todas as repetições preservadas. Ordenar [3, 1, 2] como [1, 2, 3] funciona. Tanto [1, 2] quanto [1, 1, 3] falham, embora seus vizinhos estejam em ordem. A primeira perde um elemento; a segunda altera os elementos presentes. Um rearranjo que preserva todas as ocorrências é chamado de permutação.

Em um registro, a chave é apenas o campo usado para comparação. Cidades poderiam ser ordenadas por nome ou população. O registro inteiro da cidade se move quando sua chave de população se move; separar o nome corromperia os dados.

A ordem do texto depende da chave

A comparação simples de textos segue os códigos de caracteres, um caractere por vez. Em ASCII e Unicode, A a Z usam os códigos 65 a 90 e a a z usam 97 a 122. Isso coloca “Zebra” antes de “apple” em uma comparação simples. Comparar cópias em letras minúsculas pode fornecer uma ordem que ignora maiúsculas e minúsculas nesses exemplos.

Dígitos em texto também se comportam como caracteres. “10” aparece antes de “9” porque seu primeiro caractere é “1”. Uma chave numérica converte essas cadeias de caracteres nos números que representam, colocando 9 antes de 10. Decida o que os dados significam antes de escolher a comparação.

Mova valores sem perdê-los

Uma troca permuta duas posições. Uma variável temporária protege o valor que seria sobrescrito:

temp = items[i]
items[i] = items[j]
items[j] = temp

Python também permite items[i], items[j] = items[j], items[i]. Escrever as duas atribuições sem guardar o primeiro valor transforma [4, 7] em [7, 7]. A ordenação por bolha e a por seleção movem elementos por meio de trocas; a ordenação por intercalação copia elementos para a saída intercalada.

Estabilidade e memória

Uma ordenação estável mantém a ordem original dos registros cujas chaves são iguais. Comece com Ana 85, Ben 92, Cara 85, em ordem alfabética. Uma ordenação estável por nota decrescente produz Ben 92, Ana 85, Cara 85. Ana permanece antes de Cara. Isso permite que uma ordenação posterior por nota preserve uma ordem alfabética anterior dentro de cada grupo de notas. A ordenação integrada do Python é estável.

Uma ordenação no próprio local reorganiza a lista existente com apenas algumas variáveis extras, independentemente de seu comprimento. Os métodos por bolha e por seleção ensinados aqui funcionam no próprio local. A ordenação por intercalação usual precisa de armazenamento extra proporcional ao número de elementos. Estabilidade e memória descrevem propriedades diferentes: uma ordenação pode funcionar no próprio local e ainda assim ser instável.

Meça a desordem com inversões

Uma inversão é um par de posições em que a chave de um elemento anterior é maior que a de um elemento posterior. Em [5, 1, 4, 2, 8], as inversões são (5, 1), (5, 4), (5, 2) e (4, 2): quatro no total. Os pares não precisam ser vizinhos.

Uma lista ordenada tem zero inversões. Uma lista de n elementos distintos em ordem inversa tem n(n−1)/2, o máximo. Chaves iguais nunca formam uma inversão: [3, 3, 1] tem duas, uma para cada 3 antes de 1. Contar inversões é útil para explicar a contagem de trocas da ordenação por bolha.

Principais conclusões

  • Uma ordenação correta preserva todos os elementos originais e coloca as chaves em ordem.
  • Uma chave de ordenação determina qual campo ou valor controla a ordem.
  • A estabilidade preserva a ordem dos registros com chaves iguais.
  • Uma ordenação no próprio local precisa apenas de uma quantidade fixa de armazenamento extra de trabalho.
  • Uma inversão é um par fora de ordem, incluindo pares que não são vizinhos.

2.2 Rastrear e contar as operações da ordenação por bolha

A ordenação por bolha compara elementos vizinhos da esquerda para a direita. Quando o elemento da esquerda é maior, ela troca o par. Cada percurso é uma passada. Um elemento grande pode se mover repetidamente para a direita durante uma passada, até que o maior elemento restante alcance sua posição final.

Acompanhe a primeira passada

Comece com [5, 1, 4, 2, 8]:

  1. Compare 5 e 1; troque para obter [1, 5, 4, 2, 8].
  2. Compare 5 e 4; troque para obter [1, 4, 5, 2, 8].
  3. Compare 5 e 2; troque para obter [1, 4, 2, 5, 8].
  4. Compare 5 e 8; deixe-os como estão.

A passada faz quatro comparações e três trocas. O maior elemento, 8, está posicionado. O restante ainda não está ordenado: 4 precede 2. Uma passada garante a posição final do máximo, não a ordem de todos os elementos.

A passada 2 precisa apenas das primeiras quatro posições. Compare 1 com 4, depois troque 4 com 2 e compare 4 com 5. Isso produz [1, 2, 4, 5, 8] após mais três comparações e uma troca. A passada 3 compara 1 com 2 e 2 com 4. Ela não faz trocas, confirmando que a lista está ordenada. Totais: nove comparações e quatro trocas.

Encurte cada passada e pare antecipadamente
def bubble_sort(items):
    n = len(items)
    for p in range(n - 1):
        swapped = False
        for j in range(n - 1 - p):
            if items[j] > items[j + 1]:
                items[j], items[j + 1] = items[j + 1], items[j]
                swapped = True
        if not swapped:
            break

O contador de passadas p começa em zero. O maior valor de j é n - 2 - p, portanto j + 1 permanece dentro da parte não ordenada. Reinicie swapped no começo de cada passada; uma troca em uma passada anterior não informa se a passada atual moveu algum elemento.

Após cada passada, mais uma posição à direita está em sua forma final. Uma passada sem trocas prova que todos os vizinhos comparados estão em ordem. O sufixo já posicionado também está em ordem, portanto o algoritmo pode parar. A passada de confirmação ainda conta como trabalho.

Compare o melhor e o pior caso

Para uma lista ordenada não vazia, a versão com parada antecipada faz n−1 comparações e zero trocas. Em uma lista de elementos distintos em ordem inversa, ela faz

(n−1)+(n−2)+⋯+1=n(n−1)2

comparações e o mesmo número de trocas. Cinco elementos precisam de 10; 1.000 elementos precisam de 499.500. Sem a parada antecipada, o exemplo resolvido de cinco elementos também executaria sua passada final de uma comparação, chegando a 10 comparações.

Cada troca remove exatamente uma inversão. As quatro inversões na lista original do exemplo explicam suas quatro trocas. Vizinhos iguais permanecem no lugar porque o teste usa >, tornando esta versão estável e no próprio local. Substituir > por >= pode inverter registros com chaves iguais.

A posição importa mesmo quando há poucas inversões. [5, 1, 2, 3, 4] usa quatro trocas e uma segunda passada para confirmar a ordem, totalizando sete comparações. [2, 3, 4, 5, 1] também precisa de quatro trocas, mas seu 1 só pode se mover uma vez para a esquerda por passada. Ela precisa de todas as quatro passadas e 10 comparações.

Principais conclusões

  • Cada passada posiciona o maior elemento restante à direita.
  • Uma passada sem trocas permite uma parada antecipada.
  • Conte a passada que confirma a ordem, mesmo que ela não faça trocas.
  • As comparações no pior caso são n(n−1)/2; uma entrada ordenada precisa de n−1.
  • Trocar apenas vizinhos estritamente fora de ordem preserva a estabilidade.
  • O número de trocas é igual à contagem de inversões da entrada.

2.3 Rastrear e contar as operações da ordenação por seleção

A ordenação por seleção constrói um prefixo ordenado à esquerda. Cada passada encontra o menor elemento no sufixo restante e depois o troca para a próxima posição do prefixo. A varredura encontra a posição; a troca ocorre após a varredura.

Guarde um índice

Na posição i, comece com smallest = i. Compare cada elemento posterior com items[smallest]. Atualize smallest apenas quando aparecer um elemento menor. Quando a varredura terminar, troque items[i] e items[smallest].

def selection_sort(items):
    n = len(items)
    for i in range(n - 1):
        smallest = i
        for j in range(i + 1, n):
            if items[j] < items[smallest]:
                smallest = j
        if smallest != i:
            items[i], items[smallest] = items[smallest], items[i]

Guardar apenas o menor valor deixaria você sem sua posição para a troca. Começar a varredura no índice 0 revisitaria os elementos já posicionados; a busca restante começa logo depois de i.

Rastreie as passadas

Comece com [29, 10, 14, 37, 13].

PassadaMenor elemento restanteLista após posicionamentoComparaçõesTrocas que movem elementos
110[10, 29, 14, 37, 13]41
213[10, 13, 14, 37, 29]31
314[10, 13, 14, 37, 29]20
429[10, 13, 14, 29, 37]11

O terceiro mínimo já está em sua posição, portanto nenhum valor se move. Após quatro passadas, o último elemento deve ser o maior; ele não precisa de uma passada separada. São 10 comparações e três trocas que movem elementos. A condição no código ignora trocas de uma posição com ela mesma; omitir essa condição deixa o resultado inalterado.

Comparações e trocas têm custos diferentes

A ordenação por seleção sempre faz n(n−1)/2 comparações de elementos: cada passada deve inspecionar todo o sufixo restante para identificar seu mínimo. O total é 10 para cinco elementos ou 499.500 para 1.000, mesmo com entrada já ordenada. Uma varredura que não altera o índice guardado determina o mínimo daquela passada, mas não garante, em geral, que o sufixo restante esteja ordenado.

Para uma lista não vazia, há no máximo uma troca que move elementos por passada, portanto no máximo n−1 no total. Uma entrada vazia não precisa de passadas nem de trocas. A ordenação por bolha pode precisar de n(n−1)/2 trocas em uma lista de elementos distintos em ordem inversa. Se mover registros grandes custa muito mais que comparar suas chaves, a pequena contagem de trocas da ordenação por seleção pode ser relevante apesar de suas muitas comparações. Trocar sempre que um novo mínimo aparece durante a varredura elimina essa vantagem.

Chaves iguais podem mudar de ordem

Esse método baseado em trocas funciona no próprio local, mas é instável. Identifique registros de chaves iguais como 4a e 4b para que sua identidade fique visível. Começando com [4a, 4b, 1], a primeira passada troca 4a e 1, produzindo [1, 4b, 4a]. As chaves iguais inverteram sua ordem original, embora o algoritmo nunca as tenha comparado diretamente como diferentes. Manter o primeiro mínimo encontrado durante uma varredura não impede que uma troca entre posições distantes ultrapasse um registro de mesma chave.

Principais conclusões

  • A ordenação por seleção procura um mínimo e depois faz uma troca ao fim da varredura.
  • Após cada passada, o prefixo ordenado ganha um elemento.
  • Sua contagem de comparações é sempre n(n−1)/2.
  • Para uma entrada não vazia, ela usa no máximo n−1 trocas que movem elementos e uma quantidade fixa de armazenamento extra.
  • A versão usual com trocas entre posições distantes é instável.
3

Ordenar mais rapidamente com ordenação por intercalação

Ordenar uma lista grande por meio de varreduras completas repetidas se torna custoso. A ordenação por intercalação usa outro plano: dividir a lista em partes menores, ordenar essas partes e combinar seus resultados. Primeiro, aprenda por que duas listas ordenadas podem ser intercaladas olhando apenas para seus elementos à frente. Depois, acompanhe as divisões e intercalações recursivas, observando o trabalho em cada nível e a memória extra necessária para armazenar a saída.

3.1 Intercalar duas listas ordenadas em uma só

A intercalação combina duas listas já ordenadas em uma única saída ordenada. Mantenha um marcador de posição no primeiro elemento ainda não utilizado de cada entrada. Compare esses dois elementos à frente, copie o menor e avance apenas seu marcador.

Escolha o próximo menor elemento

Intercale [3, 27, 38, 43] com [9, 10, 82]:

Comparação dos elementos à frenteCopiar para a saídaSaída até o momento
3 e 93[3]
27 e 99[3, 9]
27 e 1010[3, 9, 10]
27 e 8227[3, 9, 10, 27]
38 e 8238[3, 9, 10, 27, 38]
43 e 8243[3, 9, 10, 27, 38, 43]

A lista da esquerda está agora vazia. Copie o 82 restante sem outra comparação de elementos. O resultado é [3, 9, 10, 27, 38, 43, 82], usando seis comparações. Copiar o trecho restante faz parte do algoritmo: parar quando as comparações terminam faria perder dados.

Por que o método pode ignorar os elementos atrás dos que estão à frente? Cada elemento à frente é o menor elemento restante de sua própria lista. O menor deles é, portanto, o menor elemento restante no conjunto. Esse raciocínio continua válido após cada avanço de marcador porque as partes não utilizadas permanecem ordenadas.

Leia o código de intercalação
def merge(left, right):
    result = []
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result.extend(left[i:])
    result.extend(right[j:])
    return result

append acrescenta um elemento. Uma fatia como left[i:] contém o trecho restante não utilizado, e extend copia seus elementos. Apenas um trecho restante não utilizado pode ser não vazio quando o laço termina. Se uma entrada começar vazia, o laço faz zero comparações e a outra lista é copiada intacta.

Conte comparações e armazenamento

Para duas listas não vazias de comprimentos m e k, são necessárias no máximo m+k−1 comparações dos elementos à frente. Cada comparação posiciona um elemento, e pelo menos o último elemento pode ser copiado sem comparação. A menor contagem possível de comparações na intercalação é o comprimento da lista menor: [1, 2, 3] intercalada com [4, 5, 6] usa três comparações antes que o lado esquerdo se esgote.

O trabalho total de cópia cresce com m+k mesmo quando as comparações terminam cedo, pois cada elemento deve aparecer na saída. A nova lista também precisa de espaço para m+k elementos. A contagem de comparações, o trabalho de cópia e o armazenamento extra medem partes diferentes da mesma operação.

Trate empates e a ordem das entradas

O teste <= escolhe o elemento da esquerda quando as chaves são iguais. Se as duas entradas vieram de partes consecutivas de uma lista original, isso preserva o registro anterior antes do registro posterior de mesma chave. Essa é a regra de desempate necessária para uma ordenação por intercalação estável.

O requisito de entradas ordenadas é obrigatório. Intercalar [5, 1] com [3] copia 3 e depois o trecho restante [5, 1], produzindo [3, 5, 1]. A regra dos elementos à frente falhou porque 5 não era o menor valor restante em sua própria entrada.

Principais conclusões

  • A intercalação compara os primeiros elementos ainda não utilizados de duas entradas ordenadas.
  • Copie o trecho restante não utilizado quando um dos lados se esgotar.
  • Duas entradas não vazias precisam de no máximo m+k−1 comparações dos elementos à frente.
  • Escolher o elemento da esquerda quando as chaves são iguais preserva a ordem entre as duas metades.

3.2 Rastrear a ordenação por intercalação e explicar seu crescimento n log n

A ordenação por intercalação resolve uma tarefa grande de ordenação dividindo-a em tarefas menores. Isso é divisão e conquista: divida a lista, ordene cada metade e intercale as metades ordenadas.

Pare a divisão no caso base

Uma função é recursiva quando chama a si mesma. A ordenação por intercalação chama a si mesma com listas menores. Seu caso base retorna uma lista de zero ou um elemento sem alteração, pois essa lista já está ordenada.

def merge_sort(items):
    if len(items) <= 1:
        return items
    mid = len(items) // 2
    left = merge_sort(items[:mid])
    right = merge_sort(items[mid:])
    return merge(left, right)

As fatias dividem a entrada sem perder elementos. Para um comprimento ímpar, o lado direito tem um elemento a mais: [6, 2, 9, 4, 1, 7, 3] é dividida em [6, 2, 9] e [4, 1, 7, 3]. Ambas as metades são menores, portanto as chamadas recursivas acabam chegando ao caso base. Um caso base, por si só, não garantiria a terminação se uma chamada continuasse passando a lista original para si mesma.

Reconstrua a lista ordenada

Rastreie [38, 27, 43, 3, 9, 82, 10, 15]. Ela é dividida em duas metades de quatro elementos, depois em quatro partes de dois elementos e depois em elementos individuais. A divisão não reorganiza os valores. A ordem é construída durante as intercalações:

  1. Intercale elementos individuais em [27, 38], [3, 43], [9, 82] e [10, 15]. Cada intercalação usa uma comparação: quatro no total.
  2. Intercale pares em [3, 27, 38, 43] e [9, 10, 15, 82]. Cada intercalação usa três comparações: seis no total.
  3. Intercale essas metades em [3, 9, 10, 15, 27, 38, 43, 82]. Isso usa sete comparações.

A ordenação completa usa 4+6+7=17 comparações de elementos. Não conte apenas a intercalação final: as metades ordenadas precisaram ser produzidas primeiro. O exemplo de sete elementos acima é ordenado como [1, 2, 3, 4, 6, 7, 9] usando 14 comparações com essa regra de divisão.

Conte níveis e trabalho por nível

Para oito elementos, a divisão pela metade chega a elementos individuais após três níveis porque 23=8. Em geral, há cerca de log⁡2n níveis de intercalação. Em um nível completo, as intercalações processam coletivamente todos os n elementos. Cada nível, portanto, realiza trabalho proporcional a n, levando a um crescimento como nlog⁡2n.

Para oito elementos, nlog⁡2n=24 é um limite superior aproximado útil para comparações, não a contagem exata. A lista do exemplo usou 17; uma lista de oito elementos já ordenada ou em ordem inversa usa 12. A ordem da entrada altera o momento em que uma intercalação esgota um lado, mas toda lista ainda passa pelos níveis de divisão e intercalação. O crescimento das comparações permanece nlog⁡n nos melhores e piores casos para esta versão.

Para um milhão de elementos, cerca de 20 níveis dão cerca de 20 milhões de comparações como estimativa de limite superior. A ordenação por seleção usa cerca de 500 bilhões. A diferença cresce rapidamente com o tamanho da entrada.

Considere o espaço extra para a saída

A ordenação por intercalação comum, baseada em listas, precisa de armazenamento extra proporcional a n. Escolher o elemento da esquerda nos empates a torna estável.

Principais conclusões

  • A ordenação por intercalação ordena recursivamente duas metades menores e depois as intercala.
  • Listas de zero ou um elemento formam o caso base.
  • Comprimentos ímpares são divididos em metades que diferem em um elemento.
  • Cerca de log⁡2n níveis realizam, cada um, trabalho proporcional a n.
  • As contagens exatas de comparações dependem da ordem; a família de crescimento é nlog⁡n.
  • A versão usual é estável quando escolhe a esquerda nos empates e precisa de armazenamento extra proporcional.
4

Contar passos e comparar o crescimento dos tempos de execução

Um cronômetro mostra como um programa foi executado uma vez; uma contagem de passos ajuda a explicar o que acontece quando a entrada cresce. Escolha uma operação para contar, transforme trabalho repetido em uma fórmula e compare padrões de crescimento, desde uma única consulta até tentar todas as seleções. Use esses padrões para estimar tempos de execução e limites de tempo e depois planeje medições que possam verificar se as previsões correspondem às execuções reais.

4.1 Contar os passos executados por um algoritmo

Um tempo de execução medido depende da máquina e do programa. Uma contagem de passos descreve o trabalho do algoritmo usando uma operação repetida escolhida. O tamanho da entrada, representado por n, é o número de elementos processados.

Escolha a operação antes de contar

Para busca e ordenação, as comparações entre valores dos elementos costumam ser uma operação básica útil. Conte as trocas separadamente quando a movimentação dos dados for relevante. Para a busca binária, é conveniente contar as verificações de um elemento central. Na versão em Python, uma verificação central sem sucesso avalia tanto a igualdade quanto a relação de menor que, portanto pode envolver duas comparações de elementos.

MétodoUnidade de contagemContagem no pior caso
Busca linearComparações entre elemento e valor procuradon
Busca binária, entrada não vaziaVerificações de elementos centrais⌊log⁡2n⌋+1
Ordenação por bolhaComparações entre vizinhosn(n−1)/2
Ordenação por seleçãoComparações de chavesn(n−1)/2
Ordenação por intercalaçãoComparações dos elementos à frenteNo máximo cerca de nlog⁡2n

Essas contagens descrevem operações repetidas, não linhas de código. Uma linha dentro de um laço pode ser executada um milhão de vezes; várias linhas de preparação podem ser executadas uma vez cada.

Distinga casos do mesmo tamanho

O melhor caso exige o menor número de passos entre as entradas válidas de tamanho n. O pior caso exige o maior número e fornece uma garantia. O caso médio calcula a média segundo um padrão declarado de entradas.

Para uma lista não vazia, a busca linear precisa de uma comparação se o valor procurado estiver no início e de n se estiver no fim ou ausente. Sua média para buscas bem-sucedidas é (n+1)/2 quando a primeira posição correspondente tem a mesma probabilidade de ser qualquer posição. A palavra “média” exige essa distribuição; ela não significa o ponto médio entre as contagens do melhor e do pior caso para todo algoritmo.

Transforme laços em contagens

Uma comparação por elemento em uma varredura completa dá n comparações. Dois laços aninhados completos, cada um executado n vezes, executam seu corpo compartilhado n2 vezes. Outro padrão de laços aninhados compara cada par apenas uma vez:

for i in range(n):
    for j in range(i + 1, n):
        compare(items[i], items[j])

A primeira iteração externa compara seu elemento com n−1 elementos posteriores. A seguinte compara com n−2, e a última não compara com nenhum. O total é

1+2+⋯+(n−1)=n(n−1)2.

Escreva a soma em ordem direta e inversa. Cada par alinhado soma n, e há n−1 desses pares. Seu total é n(n−1), o dobro da soma original. Para cinco elementos, 4+3+2+1=10; para 1.000, a contagem de pares é 499.500.

Reconheça divisões sucessivas pela metade

Um laço que reduz seu trabalho restante pela metade leva cerca de log⁡2n repetições. Um milhão chega pela primeira vez a 1 ou menos após 20 divisões pela metade: 219=524.288 é menor que um milhão e 220=1.048.576 é maior. Isso é bem diferente de remover apenas um elemento a cada vez.

Para comparar o crescimento, mantenha o termo de crescimento mais rápido. A contagem de pares é n2/2−n/2. Para n=1.000, seus termos são 500.000 e 500, portanto o termo quadrático determina o crescimento. Deixar de lado o termo menor e o fator constante descreve a família de crescimento; isso não transforma a contagem exata de 499.500 em uma contagem exata de um milhão.

Principais conclusões

  • Identifique a operação contada e expresse a contagem usando o tamanho da entrada.
  • As contagens no pior caso são garantias; as médias dependem de uma distribuição de entradas.
  • Varreduras aninhadas completas produzem n2 execuções do corpo.
  • Comparar cada par distinto uma vez produz n(n−1)/2 comparações.
  • Divisões sucessivas pela metade produzem crescimento logarítmico.

4.2 Comparar como a quantidade de passos cresce com o tamanho da entrada

Uma taxa de crescimento descreve como a quantidade de trabalho muda à medida que a entrada aumenta. Ela ajuda a comparar algoritmos além do tamanho específico usado em um rastreamento.

Conheça as famílias comuns
Família de crescimentoExemploEfeito de dobrar o tamanho da entrada
Constante, 1Ler uma posição conhecida de um arrayMesmo trabalho
Logarítmica, log⁡2nBusca bináriaCerca de uma verificação extra
Linear, nVarredura completaDobro do trabalho
nlog⁡nOrdenação por intercalaçãoUm pouco mais que o dobro
Quadrática, n2Ordenação por seleçãoCerca de quatro vezes mais
Exponencial, 2nTentar todas as seleções de elementosEleva a contagem ao quadrado

No crescimento exponencial, acrescentar apenas um elemento já dobra a contagem: 2n+1=2×2n. Dobrar a entrada é uma mudança muito maior do que acrescentar um elemento.

Compare tamanhos numericamente

Para entradas de 10, 100, 1.000 e um milhão de elementos, log⁡2n é aproximadamente 3,3, 6,6, 10 e 20. Os valores correspondentes de nlog⁡2n são aproximadamente 33, 664, 9.966 e 20 milhões. Os valores quadráticos são 100, 10.000, um milhão e um trilhão.

O crescimento logarítmico não é “metade da lista”. Para um milhão de elementos, dividir repetidamente pela metade leva apenas cerca de 20 etapas. Quando a entrada aumenta de 1.000 para 2.000, nlog⁡2n aumenta de cerca de 9.966 para 21.932, um fator de cerca de 2,2. O logaritmo também muda, portanto a contagem cresce um pouco mais rápido que a linear.

O trabalho exponencial cresce rapidamente. 210=1.024 e 220 é cerca de um milhão. A um bilhão de passos por segundo, 250 passos ainda levam cerca de 13 dias. Acrescentar mais um elemento dobra esse tempo.

Use a notação O informal

Programadores geralmente identificam essas famílias como O(1), O(log⁡n), O(n), O(nlog⁡n), O(n2) e O(2n). Aqui, elas identificam a família usual de crescimento no pior caso. Leia O(n2) como “ordem de n ao quadrado”. A notação omite fatores constantes e termos de ordem inferior: n(n−1)/2 comparações pertencem à família quadrática.

Uma notação O não é um tempo de execução exato nem um número de segundos. Ela também não afirma que toda entrada usa a contagem do pior caso. A ordenação por bolha com parada antecipada tem um melhor caso linear, mas um pior caso quadrático.

Encontre o ponto de cruzamento

Suponha que o método A leve 100n passos e o método B leve n2. Para 50 elementos, A leva 5.000 passos e B leva 2.500. Para 100, ambos levam 10.000. Para 1.000, A leva 100.000 e B leva um milhão. O crescimento mais lento de A acaba superando seu fator constante maior.

A velocidade do hardware muda a escala sem mudar a família. Um computador 100 vezes mais rápido permite que um método quadrático processe apenas 10 vezes mais elementos no mesmo tempo, pois (10n)2=100n2. Um método linear poderia processar 100 vezes mais. Para uma tarefa pequena, a preparação e as constantes podem predominar; para entradas grandes, o crescimento se torna decisivo.

Principais conclusões

  • Dobrar a entrada aproximadamente dobra o trabalho linear e quadruplica o trabalho quadrático.
  • O trabalho logarítmico aumenta cerca de um passo quando a entrada dobra.
  • A ordenação por intercalação combina trabalho linear por nível com um número logarítmico de níveis.
  • Acrescentar um elemento dobra uma contagem de 2n passos.
  • As notações de crescimento omitem constantes; as contagens reais determinam os pontos de cruzamento para entradas pequenas.

4.3 Prever e medir tempos de execução

Um tempo de execução conhecido e um padrão de crescimento permitem prever como uma tarefa maior se comportará. A previsão é uma estimativa porque o tempo real também depende da implementação, da memória, do hardware e de outros trabalhos na máquina.

Ajuste a entrada e depois o tempo

Para trabalho linear, multiplique o tempo pela razão entre os tamanhos das entradas. Se uma busca no pior caso em um milhão de elementos leva 3 milissegundos, dez milhões de elementos levam cerca de 30 milissegundos em condições comparáveis.

Para trabalho quadrático, eleve a razão ao quadrado. Suponha que a ordenação por seleção leve 2 segundos para 50.000 elementos. Dobrar para 100.000 elementos resulta em

2×(100.00050.000)2=2×4=8

segundos. Aumentar para 500.000 elementos multiplica o tamanho da entrada por 10, portanto a estimativa de tempo é de 2×102=200 segundos. Multiplicar o tempo por 10 trataria incorretamente o algoritmo como linear.

Para crescimento nlog⁡2n, use a razão entre as duas expressões completas. Dobrar uma entrada grande custa um pouco mais que o dobro porque o logaritmo aumenta junto com a contagem de elementos.

Trabalhe em sentido inverso a partir de um limite de tempo

Use o mesmo tempo quadrático de referência: 2 segundos para 50.000 elementos. Um limite de 32 segundos permite 16 vezes o tempo. A entrada pode crescer pela raiz quadrada de 16, que é 4, chegando a cerca de 200.000 elementos. Verifique a relação por substituição: quatro vezes a entrada prevê 16 vezes o tempo, passando de 2 segundos para 32 segundos.

Compare algoritmos em um tamanho grande

Para um milhão de elementos, a ordenação por seleção faz 499.999.500.000 comparações, cerca de 500 bilhões. A ordenação por intercalação precisa de no máximo cerca de 20 milhões. A uma taxa hipotética de um bilhão de comparações por segundo, essas contagens correspondem a cerca de 500 segundos contra 0,02 segundos, uma diferença de aproximadamente 25.000 vezes. Esse cálculo usa o mesmo custo por comparação para isolar o efeito do algoritmo; programas medidos também têm custos de movimentação e acesso à memória.

Teste uma previsão de crescimento

Meça o tempo do mesmo programa em vários tamanhos que dobram, como 10.000, 20.000 e 40.000 elementos. Divida cada tempo pelo anterior. Razões próximas de 2 sugerem crescimento linear; um pouco acima de 2 sugere nlog⁡n; próximas de 4 sugerem crescimento quadrático.

Mantenha a máquina e o método de medição consistentes. Repita as execuções e use tamanhos grandes o suficiente para que o tempo de inicialização não predomine. Compare casos semelhantes: buscar na primeira posição em um tamanho e fazer uma busca sem sucesso em outro misturaria os efeitos da entrada com o crescimento. Para a ordenação por bolha, listas ordenadas e listas em ordem inversa precisam de identificações de caso diferentes.

Se tamanhos que dobram resultarem em 0,04, 0,16 e 0,64 segundos, ambas as razões serão 4, apoiando um modelo quadrático nesse intervalo. Uma única razão sujeita a ruído é uma evidência mais fraca que um padrão repetido. Contagens de passos para um rastreamento específico podem ser exatas; uma previsão em segundos deve usar “cerca de” e ser verificada por medições.

Principais conclusões

  • O tempo linear varia conforme a razão das entradas; o tempo quadrático varia conforme seu quadrado.
  • Para um limite de tempo quadrático, use uma raiz quadrada para recuperar a razão entre os tamanhos das entradas.
  • Meça vários tamanhos com casos de entrada comparáveis e execuções repetidas.
  • Razões entre tempos sugerem padrões de crescimento; previsões em segundos continuam sendo estimativas.
5

Justificar a correção e escolher o algoritmo adequado

Um rastreamento rápido em uma lista deixa duas perguntas em aberto: o algoritmo sempre funcionará e é adequado a esta tarefa? Defina o que significam entrada válida e saída correta, use um invariante de laço para explicar por que o método mantém seu progresso e mostre por que ele para. Depois, escolha testes que revelem erros nos limites e compare algoritmos usando as necessidades reais da tarefa quanto a tempo, memória, estabilidade e acesso aos dados.

5.1 Justificar que um algoritmo está correto

Um algoritmo correto para em toda entrada válida e produz a saída exigida. Uma especificação estabelece a condição da entrada e o resultado prometido. Para a busca binária, a pré-condição é a ordem crescente. A pós-condição é um índice correspondente ou -1 exatamente quando o valor procurado está ausente.

Use um invariante para conectar os passos

Um invariante de laço é uma afirmação que vale antes do início do laço e é preservada por cada repetição. Um argumento de correção verifica seu início, sua preservação e o que ele implica quando o laço termina. Separadamente, um argumento de terminação mostra que o laço acaba terminando.

Para a ordenação por seleção, use este invariante: antes da passada i, as primeiras i posições contêm os i menores elementos em ordem.

  1. Início: antes da passada 0, o prefixo está vazio. Ele já satisfaz a afirmação.
  2. Preservação: a passada encontra o menor elemento restante. Colocá-lo em seguida estende o prefixo ordenado em um elemento, e esse elemento é pelo menos tão grande quanto cada elemento posicionado anteriormente.
  3. Fim: após no máximo n−1 passadas, apenas o maior elemento permanece fora do prefixo. Toda a lista está ordenada.

Cada movimentação é uma troca, portanto o multiconjunto de elementos também permanece inalterado. Uma saída em ordem, por si só, não atenderia à especificação completa da ordenação.

A ordenação por bolha usa um invariante de sufixo: após k passadas, as últimas k posições contêm os k maiores elementos em ordem. A passada seguinte leva o maior elemento não ordenado até esse sufixo. Uma passada sem trocas estabelece a ordem em toda a parte restante, permitindo a terminação antecipada.

Explique os intervalos descartados pela busca binária

Use o invariante: se o valor procurado aparece, pelo menos uma ocorrência está dentro do intervalo inclusivo de low a high. Inicialmente, esse intervalo cobre toda a lista. Se o valor central for pequeno demais, a ordem da lista torna pequeno demais todo valor em mid ou à sua esquerda. Atualizar low para mid + 1 preserva todas as correspondências possíveis. A atualização para high = mid - 1 segue o mesmo raciocínio para valores grandes demais.

Quando há uma correspondência, a posição retornada atende diretamente à pós-condição. Se o intervalo se esvaziar, o invariante descarta a presença do valor procurado em qualquer lugar da lista. A entrada permanece ordenada porque a busca nunca a altera.

Mostre por que a execução para

Uma medida inteira não negativa que diminui prova o progresso em direção ao fim. Na busca binária, o número de posições candidatas diminui estritamente após cada não correspondência. A posição central testada é excluída, portanto o laço não pode manter o mesmo intervalo para sempre. A ordenação por bolha e a por seleção fazem no máximo n−1 passadas em uma entrada não vazia e nenhuma passada em uma entrada vazia.

A ordenação por intercalação chega a listas de zero ou um elemento porque cada chamada recursiva usa uma lista menor. Esses casos base estão ordenados. Supondo que as chamadas menores retornem metades ordenadas corretamente, a intercalação escolhe repetidamente o menor elemento restante e preserva todos os elementos. Isso leva a correção de volta até a chamada original.

Use testes para outra finalidade

Um teste compara um resultado real com um resultado esperado. Passar em muitos testes selecionados aumenta a confiança, enquanto uma única entrada válida que falha é um contraexemplo que refuta a correção. Um argumento geral com invariante cobre a família ilimitada de entradas possíveis que uma coleção finita de testes de exemplo deixa sem verificar. Os testes são especialmente úteis para verificar se o código real implementa o método usado no argumento.

Principais conclusões

  • A correção exige o resultado especificado e a terminação em toda entrada válida.
  • Um invariante deve valer inicialmente, permanecer verdadeiro a cada iteração e sustentar o resultado na saída.
  • Um argumento de ordenação deve preservar os elementos e estabelecer a ordem.
  • Uma medida não negativa que diminui estritamente estabelece a terminação.
  • Uma única entrada válida que falha refuta a correção.

5.2 Testar algoritmos com casos-limite

Um caso-limite é uma entrada válida próxima de um limite em que é fácil errar suposições e limites de laço. Planeje o resultado esperado com base na especificação antes de executar o código. Caso contrário, a saída errada de um programa pode se tornar discretamente sua resposta esperada.

Escolha listas que exercitem os limites

Teste listas vazias, de um elemento e de dois elementos; listas já ordenadas e em ordem inversa; valores repetidos e todos iguais; números negativos; e comprimentos ímpares e pares. Para buscas, inclua a primeira posição, a última posição e valores procurados ausentes abaixo, acima e entre os valores armazenados.

Uma busca binária vazia deve retornar -1 sem acessar um elemento: low = 0 e high = -1 tornam o intervalo inicial vazio. Ordenar [3, 3, 3] deve retornar três cópias de 3. Uma saída [3] estaria ordenada, mas não preservaria os elementos.

Rastreie a menor falha

Uma busca binária que usa while low < high não entra no laço para [5] com valor procurado 5. A correção é low <= high, pois um intervalo de uma posição ainda contém um candidato. Esse teste com um elemento isola o limite mais claramente que uma lista longa.

Com low = mid, buscar 20 em [10, 20] define a posição central como 0, vê 10 e deixa low em 0. O intervalo permanece inalterado na repetição seguinte. Use low = mid + 1 para excluir uma posição já verificada. Uma lista de dois elementos com o valor procurado no fim revela esse laço infinito.

A ordenação por bolha compara items[j] com items[j + 1]. Na primeira passada, o último índice válido à esquerda é n - 2. Continuar até n - 1 acessa uma posição além da lista e provoca o IndexError do Python. Esse erro de uma posição no limite é chamado de erro de uma unidade.

Verifique as duas garantias da saída

Para uma ordenação, verifique a ordem dos elementos adjacentes e a contagem de cada elemento original. Use registros identificados para testar a estabilidade. Ana 85, Ben 92, Cara 85 deve manter Ana antes de Cara quando uma ordenação estável por nota agrupa as notas iguais. Uma verificação apenas das notas não perceberia uma troca desses dois registros.

Gere listas aleatórias também. Compare seus resultados com uma implementação confiável, como sorted do Python. Mantenha duplicatas e comprimentos diferentes nas entradas geradas. Quando um teste falhar, reduza a entrada preservando a falha e depois rastreie-a manualmente. Mantenha o pequeno exemplo como teste de regressão para que o erro corrigido continue detectável.

Mantenha segura a aritmética da posição central

Os inteiros do Python crescem conforme necessário, portanto (low + high) // 2 não causa estouro. Algumas linguagens usam inteiros de largura fixa. Para índices não negativos muito grandes, sua soma pode ultrapassar a faixa armazenável. A soma de inteiros em Java retorna ciclicamente; o estouro de inteiro com sinal em C tem comportamento indefinido.

Com índices válidos e low <= high, calcule low + (high - low) // 2. A diferença é não negativa, e o resultado permanece entre os extremos. Isso calcula a mesma posição central arredondada para baixo sem formar a soma que poderia causar estouro. O teste de limites e o raciocínio sobre a representação numérica da linguagem trabalham juntos aqui.

Principais conclusões

  • Escreva os resultados esperados antes de executar os testes.
  • Listas pequenas revelam verificações finais ausentes, intervalos inalterados e acesso inválido a vizinhos.
  • Verifique a preservação dos elementos, a ordem e a estabilidade quando ela for necessária.
  • Reduza entradas aleatórias que falham e mantenha-as como testes de regressão.
  • A posição central calculada pela diferença evita estouro para índices válidos, não negativos e de largura fixa.

5.3 Escolher um algoritmo adequado à situação

Um algoritmo é adequado a uma tarefa quando seus requisitos e custos correspondem aos dados e ao trabalho realizado. Considere a ordem da entrada, o acesso às posições, o número de operações futuras, a memória extra, a estabilidade e o custo de movimentar registros.

Compare os métodos
MétodoPadrão de tempo ou de passosArmazenamento extraEstável?
Busca linearAté n comparaçõesFixoNão é uma propriedade de ordenação
Busca bináriaAté ⌊log⁡2n⌋+1 verificações centraisFixoNão é uma propriedade de ordenação
Ordenação por bolha com parada antecipadan−1 comparações se ordenada; pior caso quadráticoFixoSim, com trocas estritas
Ordenação por seleçãon(n−1)/2 comparações; no máximo n−1 trocas que movem elementosFixoNão, na forma usual com trocas
Ordenação por intercalaçãoCrescimento nlog⁡n de comparaçõesProporcional a nSim, escolhendo a esquerda nos empates

A busca binária também precisa de ordem e acesso rápido ao meio. Uma boa comparação inclui esses pré-requisitos; uma contagem pequena de buscas, por si só, deixa de fora o custo de preparar dados inadequados.

Decida se compensa ordenar primeiro

Para uma busca em um milhão de elementos não ordenados, a busca linear custa no máximo um milhão de comparações. Ordenar primeiro por intercalação custa cerca de 20 milhões de comparações antes da primeira busca binária, que então precisa de no máximo 20 verificações centrais. A preparação supera a economia nessa única consulta.

Para 100 consultas em uma lista inalterada, buscas lineares repetidas podem custar 100 milhões de comparações. Ordenar uma vez e fazer 100 buscas binárias custa cerca de 20 milhões de comparações mais 2.000 verificações centrais. A preparação é reutilizada, tornando o segundo plano atraente. Nesse modelo aproximado de custo, o ponto de equilíbrio é de cerca de 20 buscas. A estimativa depende de custos comparáveis das operações e de varreduras no pior caso; não é um limite universal de consultas.

Pondere ordem, movimentação e memória

A ordenação por bolha pode terminar rapidamente quando apenas um par próximo está fora de lugar. [1, 2, 4, 3, 5] precisa de uma troca na primeira passada e de uma segunda passada para confirmar a ordem: sete comparações. Mas “quase ordenada” não garante poucas passadas. Um valor pequeno na extrema direita só pode se mover uma posição para a esquerda a cada passada.

As poucas trocas da ordenação por seleção ajudam quando é custoso mover registros. Tanto a ordenação por seleção quanto a por bolha usam apenas uma quantidade fixa de armazenamento extra. A ordenação por intercalação processa listas grandes com crescimento de tempo muito mais lento, mas sua forma usual baseada em listas precisa de espaço para aproximadamente mais uma lista de elementos.

Se registros com chaves iguais precisarem manter uma ordem anterior, escolha um método estável. Uma lista já em ordem alfabética por nome pode ser ordenada de forma estável por nota, permanecendo em ordem alfabética dentro de cada grupo de notas. A ordenação por seleção comum pode alterar a ordem desses empates.

Use ferramentas de biblioteca testadas

Programas reais geralmente usam a ordenação integrada da linguagem. A ordenação estável do Python usa um método adaptativo baseado em intercalação, geralmente chamado Timsort, que se beneficia da ordem já presente na entrada. sorted(items) retorna uma nova lista, enquanto items.sort() altera a lista existente. Um método que altera uma lista no próprio local como comportamento de sua API ainda pode usar memória de trabalho temporária internamente; ele não precisa satisfazer a definição de armazenamento extra fixo usada para as ordenações simples acima.

Para poucos elementos, um código simples e claro pode importar mais que o crescimento. Para coleções grandes, compare o comportamento no pior caso e a memória junto com as propriedades que a tarefa realmente exige.

Principais conclusões

  • Inclua o custo de preparação ao comparar buscas em dados não ordenados.
  • Buscas repetidas podem compensar uma ordenação feita uma única vez.
  • A ordenação por seleção limita as trocas; a por intercalação limita o crescimento do tempo, mas precisa de armazenamento extra.
  • Use uma ordenação estável para preservar a ordem anterior dentro de grupos de chaves iguais.
  • Ordenações integradas oferecem implementações testadas; entradas pequenas podem favorecer a simplicidade.

Exercícios resolvidos de Algoritmos de busca e ordenação

5 Lições Interativas

1

Encontrar um valor procurado sem perder o controle das posições

13 passos
Rastrear a busca linear e a binária, contar seu trabalho e verificar os limites de cada busca.
  1. 1
    IntroduçãoEncontrar um valor e informar sua posição

    Uma busca deve distinguir um valor armazenado de sua posição. Em [7, 3, 9, 3, 5], as posições vão de 0 a 4. O valor 3 aparece nos índices 1 e 3.

    Primeiro verificaremos as posições em ordem (busca linear) e depois usaremos a ordem da lista para excluir grupos de posições (busca binária), contando comparações para ver quanto trabalho cada método realiza. Ambos os métodos retornam um índice em caso de sucesso e -1 quando o valor procurado está ausente.

  2. 2
    ExplicaçãoUse uma não correspondência para descartar uma posição

    A busca linear compara o valor procurado com cada elemento da esquerda para a direita. Uma correspondência encerra a busca imediatamente; uma não correspondência leva à próxima posição.

    Uma lista não ordenada não oferece motivo para rejeitar elementos posteriores após uma não correspondência inicial. Por isso, o retorno “não encontrado” deve ficar após o laço, quando todas as posições tiverem sido verificadas.

  3. 3
    ExemploEncontre o primeiro 3

    Busque 3 em [7, 3, 9, 3, 5].

    No índice 0, 7 é diferente de 3, então continue. No índice 1, o valor armazenado é 3, então retorne 1 após duas comparações.

    O segundo 3 nunca é examinado. O índice retornado é 1, enquanto o número de comparações é 2; esses números descrevem partes diferentes do rastreamento.

  4. 4
    DesafioRastreie uma correspondência posterior

    A busca linear procura 11 em [19, 4, 11, 4, 8]. Qual índice ela retorna e quantas comparações faz?

    ---reveal---

    Ela retorna o índice 2 após três comparações: 19, 4 e depois 11. Um retorno de falha após a primeira não correspondência pararia incorretamente em 19. O índice 2 é a terceira posição porque as posições começam em zero.

  5. 5
    Ideia-chaveDeixe o valor procurado determinar quando parar

    Para uma lista não vazia de n elementos, a busca linear usa uma comparação no melhor caso e n no pior. Uma lista vazia usa zero.

    Com uma ocorrência do valor procurado igualmente provável em cada posição, a média das buscas bem-sucedidas é (n+1)/2. Contar todas as ocorrências muda a tarefa: mesmo uma correspondência inicial não pode encerrar essa varredura completa.

  6. 6
    AnalogiaUse a ordem para descartar um lado

    Um dicionário permite seguir para a metade que contém a palavra desejada. A busca binária usa a mesma ideia de ordenação com limites exatos de índices.

    Sua pré-condição são dados ordenados. Se um número central for pequeno demais, todos os números anteriores também serão pequenos demais. Sem ordem, uma comparação com o meio não fornece essa informação sobre as outras posições.

  7. 7
    ExplicaçãoMantenha os dois extremos em análise

    Comece com low = 0 e high = n - 1. Enquanto low <= high, calcule mid = (low + high) // 2.

    Retorne mid se houver correspondência. Se seu valor for pequeno demais, defina low = mid + 1; se for grande demais, defina high = mid - 1. A posição central testada é excluída após qualquer uma das não correspondências, portanto cada atualização reduz o intervalo de posições candidatas.

  8. 8
    ExemploVerifique o meio e depois a metade direita

    Encontre 64 em [3, 8, 12, 17, 23, 31, 42, 56, 64, 77, 85]. Os limites iniciais são 0 e 10. Sua posição central arredondada para baixo é 5, que contém 31.

    Como 31 é menor que 64, defina low = 6. Os limites restantes 6 e 10 dão a posição central 8. Seu valor é 64, então retorne 8 após duas verificações de elementos centrais.

  9. 9
    ExemploVeja um valor ausente esvaziar o intervalo

    Nessa mesma lista ordenada, busque 20. Os índices e valores verificados são 5 → 31, 2 → 12, 3 → 17 e 4 → 23.

    As atualizações deixam low = 4, high = 3. Não resta nenhum candidato, então retorne -1. A última verificação foi necessária: extremos iguais imediatamente antes dela significavam um candidato, não um intervalo vazio.

  10. 10
    DesafioRecalcule a posição central após cada atualização

    Busque 34 em [2, 7, 13, 21, 34, 55] usando limites inclusivos e posições centrais arredondadas para baixo. Quais índices são verificados?

    ---reveal---

    Primeiro, verifique o índice 2, que contém 13. Defina low = 3, enquanto high permanece em 5, portanto a próxima posição central é 4. Ela contém 34: retorne 4 após duas verificações. A posição depois de 2 não era automaticamente a próxima posição central.

  11. 11
    DicaVerifique o último candidato e exclua os anteriores

    low <= high verifica um intervalo de uma posição. Uma condição estrita com < deixa de encontrar 5 em [5].

    Use mid + 1 e mid - 1 após não correspondências. Com low = mid, uma busca por 20 em [10, 20] pode repetir a posição central 0 para sempre. Se houver correspondências duplicadas, esta versão retorna um índice correspondente, sem garantir que seja o primeiro.

  12. 12
    DesafioEscolha uma busca para a entrada disponível

    Você tem uma lista não ordenada e precisa fazer uma consulta, sem tempo para preparar uma cópia ordenada. Qual busca ensinada pode ser aplicada diretamente e por quê?

    ---reveal---

    A busca linear pode ser aplicada porque cada verificação de igualdade é válida sem nenhuma ordem. A busca binária precisa de ordem para justificar os intervalos que descarta. Uma pequena contagem de verificações centrais não compensa uma pré-condição não atendida.

  13. 13
    RecapitulaçãoUse a evidência adequada para parar

    A busca linear para na primeira correspondência ou após uma varredura completa. A busca binária usa a ordem e o acesso rápido por índice para reduzir um intervalo inclusivo.

    Registre o índice retornado separadamente da contagem de trabalho. A busca binária precisa de no máximo ⌊log⁡2n⌋+1 verificações centrais para uma entrada não vazia, mas cada verificação pode conter mais de uma comparação no código.

2

Construir a ordem com trocas entre vizinhos e entre posições distantes

16 passos
Verificar os requisitos de ordenação, rastrear a ordenação por bolha e a por seleção e comparar seus custos.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoDefina com precisão a tarefa de ordenação
  2. 2
    ExplicaçãoPreserve os elementos e a ordem
  3. 3
    ExemploVeja o que a estabilidade preserva
  4. 4
    DesafioVerifique as duas condições da ordenação
  5. 5
    ExplicaçãoLeve um elemento grande para a direita
  6. 6
    ExemploAcompanhe três trocas sucessivas
  7. 7
    ExemploConte a passada de confirmação
  8. 8
    DesafioCompare trocas e comparações
  9. 9
    Ideia-chaveConte inversões para contar trocas
  10. 10
    ExplicaçãoSelecione um mínimo antes de movê-lo
  11. 11
    ExemploPosicione os dois primeiros mínimos
  12. 12
    ExemploTermine sem trocar um valor com ele mesmo
  13. 13
    DesafioEncontre um mínimo após o prefixo
  14. 14
    Ideia-chaveUma troca distante pode ultrapassar uma chave igual
  15. 15
    DesafioEscolha um método para movimentação custosa
  16. 16
    RecapitulaçãoAcompanhe a região que cada método posiciona
3

Dividir uma lista e reconstruí-la com intercalações

13 passos
Acompanhar a operação de intercalação, depois rastrear uma ordenação por intercalação recursiva completa e contar seus níveis.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoUse a ordem já construída em partes menores
  2. 2
    ExplicaçãoCompare apenas os elementos à frente ainda não utilizados
  3. 3
    ExemploIntercale os primeiros valores
  4. 4
    ExemploCopie o trecho restante após o fim das comparações
  5. 5
    DesafioConclua uma intercalação e sua contagem
  6. 6
    ExplicaçãoTorne cada problema recursivo menor
  7. 7
    ExemploDivida oito elementos em elementos individuais
  8. 8
    ExemploReconstrua pares e metades
  9. 9
    ExemploConte cada nível de intercalação
  10. 10
    DesafioInclua o trabalho dentro das metades
  11. 11
    ConexãoPreserve os empates durante a reconstrução
  12. 12
    DesafioAplique o método a uma ordenação estável grande
  13. 13
    RecapitulaçãoConte os elementos em todos os níveis
4

Transformar trabalho repetido em uma estimativa de tempo

14 passos
Contar execuções de laços, comparar famílias de crescimento e estimar tempos de execução e limites de tempo.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoPergunte quanto trabalho o próximo tamanho exige
  2. 2
    ExplicaçãoEscolha o que conta como passo
  3. 3
    ExemploConte cada par apenas uma vez
  4. 4
    DesafioLeia os limites antes de identificar o crescimento
  5. 5
    Ideia-chaveMantenha o caso junto da contagem
  6. 6
    ExplicaçãoExperimente o teste de duplicação
  7. 7
    ExemploDistinga uma notação de crescimento de uma contagem exata
  8. 8
    DesafioEncontre um ponto de cruzamento com modelos exatos
  9. 9
    ConexãoVeja o limite de um hardware mais rápido
  10. 10
    ExemploAjuste um tempo quadrático medido
  11. 11
    DesafioRecupere um tamanho de entrada a partir de um limite de tempo
  12. 12
    DicaMeça repetidamente casos comparáveis
  13. 13
    DesafioUse as razões observadas para uma previsão
  14. 14
    RecapitulaçãoLeve o modelo de contagem para a estimativa
5

Mostrar que um algoritmo funciona e é adequado à tarefa

15 passos
Usar invariantes, argumentos de terminação, testes de casos-limite e comparações de custos para avaliar um algoritmo.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoBusque uma garantia e uma adequação prática
  2. 2
    ExplicaçãoDeclare as garantias antes de demonstrá-las
  3. 3
    ExemploEstenda o invariante da ordenação por seleção
  4. 4
    ExemploPreserve uma correspondência possível e reduza seu intervalo
  5. 5
    DesafioDistinga preservação de terminação
  6. 6
    ExplicaçãoPreveja resultados nos limites antes de executar
  7. 7
    ExemploDeixe um intervalo de dois elementos revelar um laço
  8. 8
    DesafioEncontre o limite do laço de vizinhos
  9. 9
    DicaMantenha um teste mínimo que falha
  10. 10
    ExplicaçãoInclua o custo de preparação
  11. 11
    ExemploReutilize a lista ordenada em várias consultas
  12. 12
    DesafioCalcule se a preparação compensa
  13. 13
    ConexãoConsidere propriedades junto com o crescimento do tempo
  14. 14
    DesafioAssocie a correção a um requisito prático
  15. 15
    RecapitulaçãoUse argumentos, testes e custos em conjunto

Questões de Algoritmos de busca e ordenação

40 Questões de Prática em 4 conjuntos

Conjunto 1: Contar o trabalho e escolher métodos práticos10 Questões de Prática

Questão 1 de 10

Uma busca linear informa que o valor procurado está ausente em uma lista não ordenada de 9 elementos. Quantas comparações entre elemento e valor procurado ela faz?
  1. 0
  2. 1
  3. 8
  4. 9
Mostrar respostaOcultar resposta
Resposta: D
Todas as nove posições devem ser verificadas antes de estabelecer a ausência. Uma não correspondência descarta apenas uma posição em uma lista não ordenada. Uma contagem de oito deixa a última posição sem verificar, onde o valor procurado ainda poderia estar.

Questão 2 de 10

A busca binária usa limites inclusivos e uma posição central arredondada para baixo. Em [6, 12, 18, 25, 33, 46], quais são os limites imediatamente após a primeira verificação do valor procurado 30?
  1. Limite inferior 2, superior 5
  2. Limite inferior 3, superior 5
  3. Limite inferior 0, superior 1
  4. Limite inferior 0, superior 2
Mostrar respostaOcultar resposta
Resposta: B
Os limites iniciais são 0 e 5, portanto a primeira posição central é 2 e contém 18. Como 30 é maior, o novo limite inferior é 3 e o limite superior permanece em 5. Manter o limite inferior em 2 conservaria um elemento já verificado e reconhecido como pequeno demais.

Questão 3 de 10

A ordenação por bolha com parada antecipada usa passadas mais curtas em [1, 3, 2, 4]. Quantas comparações ela faz antes de parar?
  1. 3
  2. 4
  3. 5
  4. 6
Mostrar respostaOcultar resposta
Resposta: C
A primeira passada faz três comparações e troca 3 com 2. Uma segunda passada faz duas comparações, não encontra trocas e para, totalizando cinco comparações. Contar apenas três ignora a passada necessária para confirmar que o prefixo restante está ordenado.

Questão 4 de 10

A ordenação por seleção padrão recebe 6 elementos já ordenados. Quantas comparações de elementos ela faz?
  1. 15
  2. 5
  3. 0
  4. 30
Mostrar respostaOcultar resposta
Resposta: A
A ordenação por seleção ainda percorre cada sufixo restante, produzindo 5+4+3+2+1=15 comparações. A ordem evita trocas que movem elementos, mas não elimina essas varreduras. Cinco comparações corresponderiam a uma passada da ordenação por bolha, não a todas as passadas da ordenação por seleção.

Questão 5 de 10

Uma intercalação de [1, 8, 13] e [4, 9] conta apenas as comparações entre os elementos à frente. Quantas ela faz?
  1. 2
  2. 3
  3. 4
  4. 5
Mostrar respostaOcultar resposta
Resposta: C
As comparações dos elementos à frente escolhem 1, 4, 8 e 9, usando quatro comparações. O lado direito então se esgota, e 13 é copiado sem comparação. Contar cinco mistura a cópia final com a operação de comparação escolhida.

Questão 6 de 10

Um laço é executado n vezes. Em cada repetição, um segundo laço é executado exatamente 4 vezes. Quantas vezes o corpo interno é executado?
  1. n+4
  2. n2
  3. 4n
  4. 4n
Mostrar respostaOcultar resposta
Resposta: D
Cada uma das n repetições externas contribui com quatro execuções internas, portanto o total é 4n. Os laços são aninhados, mas a contagem interna é fixa, não n. Chamar todo programa com laços aninhados de quadrático ignora os limites reais de seus laços.

Questão 7 de 10

Um método quadrático de ordenação leva 3 segundos para 12.000 elementos. Aproximadamente quanto tempo deve levar para 36.000 elementos em condições comparáveis?
  1. 27 segundos
  2. 9 segundos
  3. 18 segundos
  4. 81 segundos
Mostrar respostaOcultar resposta
Resposta: A
A entrada cresce por um fator de 3, portanto um tempo quadrático cresce por 32=9. Multiplicar o tempo de referência de 3 segundos por 9 dá cerca de 27 segundos. Uma estimativa de 9 segundos ajusta o tempo diretamente à entrada e trata o método como linear.

Questão 8 de 10

Uma ordenação recebe [4, 4, -2] e retorna [-2, 4]. Qual requisito ela violou?
  1. Ordenar as chaves de forma crescente
  2. Preservar todas as ocorrências
  3. Retornar o menor valor primeiro
  4. Colocar os valores negativos primeiro
Mostrar respostaOcultar resposta
Resposta: B
As duas cópias de 4 na entrada devem ser mantidas, portanto a saída correta é [-2, 4, 4]. A lista retornada está em ordem crescente, mas perde uma ocorrência. Verificar apenas a ordem dos vizinhos aceitaria, portanto, um resultado que não atende à especificação de ordenação.

Questão 9 de 10

Para uma coleção não ordenada e inalterada, use estas estimativas de custo: ordenar custa 9.000 unidades, cada consulta binária custa 12 unidades e cada consulta linear custa 600 unidades. Qual plano custa menos para 20 consultas e quanto economiza?
  1. Consultas lineares, por 2.760 unidades
  2. Consultas lineares, por 3.000 unidades
  3. Ordenar e buscar por binária, por 3.000 unidades
  4. Ordenar e buscar por binária, por 2.760 unidades
Mostrar respostaOcultar resposta
Resposta: D
Vinte consultas lineares custam 12.000 unidades. Ordenar uma vez e fazer vinte consultas binárias custa 9.000+240=9.240 unidades, economizando 2.760. Uma economia de 3.000 subtrai a ordenação do total linear, mas esquece que as consultas binárias ainda têm custo.

Questão 10 de 10

Uma tarefa só pode usar uma quantidade fixa de armazenamento extra de trabalho e deve minimizar as trocas. Entre os métodos de ordenação ensinados, qual escolha melhor atende a essas prioridades?
  1. Ordenação por intercalação, escolhendo a esquerda nos empates
  2. Ordenação por seleção, com uma troca por passada
  3. Ordenação por bolha, com um indicador de parada antecipada
  4. Ordenação por intercalação, com uma única intercalação final
Mostrar respostaOcultar resposta
Resposta: B
A ordenação por seleção usa armazenamento extra fixo e no máximo uma troca que move elementos por passada, totalizando no máximo n−1 trocas. A ordenação por bolha também usa armazenamento fixo, mas pode precisar de uma troca para cada inversão. A ordenação por intercalação comum precisa de armazenamento de saída proporcional, portanto não atende ao requisito de memória indicado.
Conjunto 2: Encontrar valores e acompanhar os algoritmos10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Um método leva exatamente n2 passos. Como a contagem muda quando o tamanho da entrada dobra?
  1. Ela dobra.
  2. Ela triplica.
  3. Ela quadruplica.
  4. Ela não muda.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

A busca linear procura 7 em [12, 7, 18, 7]. Qual índice ela retorna?
  1. 0
  2. 1
  3. 2
  4. 3
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

A busca binária usa limites inclusivos e uma posição central arredondada para baixo em [4, 9, 15, 22, 30, 41, 57]. Quais índices ela verifica ao buscar 41?
  1. 3, 4, 5
  2. 3, 6, 5
  3. 4, 5
  4. 3, 5
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Uma função de ordenação recebe [6, 2, 6, 1]. Qual saída atende à especificação de ordenação crescente?
  1. [1, 2, 6, 6]
  2. [1, 2, 6]
  3. [1, 2, 2, 6]
  4. [6, 6, 2, 1]
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Qual lista resta após uma passada completa da esquerda para a direita da ordenação por bolha em [8, 3, 6, 2]?
  1. [3, 6, 8, 2]
  2. [2, 3, 6, 8]
  3. [3, 6, 2, 8]
  4. [3, 8, 2, 6]
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Intercale [2, 11] com [5, 14, 19]. Após copiar 11, quais elementos ainda devem ser copiados?
  1. 5 e 19
  2. 14 e 19
  3. Apenas 19
  4. 11 e 14
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Uma chamada da ordenação por intercalação recebe [16]. O que ela deve retornar?
  1. [16] imediatamente
  2. [] imediatamente
  3. [16, 16] após intercalar
  4. [] após dividir
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um algoritmo compara uma vez cada par de posições distintas em uma lista de 7 elementos. Quantas comparações de elementos ele faz?
  1. 49
  2. 42
  3. 28
  4. 21
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

A ordenação por seleção posicionou os quatro menores elementos em ordem nos índices de 0 a 3. Por que escolher o mínimo a partir do índice 4 e trocá-lo para o índice 4 preserva essa propriedade do prefixo?
  1. O sufixo restante já está ordenado.
  2. O quinto elemento não muda em nenhuma varredura.
  3. O novo elemento não é menor que os quatro posicionados.
  4. As trocas anteriores removeram todas as inversões.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Uma busca binária com limites inclusivos usa por engano while low < high. Qual é o menor teste não vazio que revela um valor procurado presente que não é encontrado?
  1. [13], valor procurado 13
  2. [13], valor procurado 8
  3. [8, 13], valor procurado 8
  4. [8, 13], valor procurado 20
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 3: Explicar limites e comparar compromissos entre critérios10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

A busca binária usa limites inclusivos e posições centrais arredondadas para baixo em [5, 11, 16, 24, 38, 47, 59, 70]. Quais índices são verificados para o valor procurado ausente 41?
  1. 3, 5, 4
  2. 3, 4, 5
  3. 4, 6, 5
  4. 3, 5, 6
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Os registros chegam como Eli 72, Jo 65, Kai 72, Luz 65. Qual ordem resulta de uma ordenação estável por nota crescente?
  1. Luz, Jo, Eli, Kai
  2. Jo, Luz, Kai, Eli
  3. Jo, Luz, Eli, Kai
  4. Eli, Kai, Jo, Luz
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Qual é a lista após a segunda passada da ordenação por seleção em [18, 7, 12, 4, 9]?
  1. [4, 7, 9, 12, 18]
  2. [7, 4, 12, 18, 9]
  3. [4, 9, 12, 18, 7]
  4. [4, 7, 12, 18, 9]
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

A ordenação por intercalação divide uma lista de 32 elementos em metades até chegar a elementos individuais. Quantos níveis de intercalação a reconstroem?
  1. 4
  2. 5
  3. 6
  4. 16
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

O método P usa 60n passos e o método Q usa n2. Para tamanhos de entrada positivos, quando P usa menos passos?
  1. Quando n>60
  2. Quando n<60
  3. Quando n≥60
  4. Quando n≤60
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Um processo quadrático leva 5 segundos para 8.000 elementos. Um limite de 45 segundos permite aproximadamente quantos elementos no mesmo modelo?
  1. 24.000 elementos após multiplicar por 9
  2. 72.000 elementos após multiplicar por 9
  3. 16.000 elementos após multiplicar por 2
  4. 24.000 elementos após multiplicar por 3
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Uma busca binária inclusiva preserva todas as correspondências possíveis dentro de seu intervalo, mas, após uma posição central de valor baixo, define low = mid. Que parte de um argumento completo de correção pode falhar?
  1. A pré-condição de ordem da entrada
  2. A garantia de que a execução para
  3. O teste de igualdade em uma correspondência
  4. A preservação dos elementos originais
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Uma lista já está ordenada por horário de chegada. Ela deve agora ser ordenada por prioridade, mantendo a ordem de chegada entre prioridades iguais. Qual propriedade de ordenação é necessária?
  1. Armazenamento extra fixo
  2. Poucas trocas que movem elementos
  3. Estabilidade entre chaves iguais
  4. Um limite quadrático de comparações
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma passada completa da ordenação por bolha não faz trocas. O que isso estabelece sobre toda a lista, incluindo qualquer sufixo já posicionado?
  1. Ela está ordenada.
  2. Seus valores são distintos.
  3. Ela tem um elemento.
  4. Suas chaves são iguais.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Uma intercalação estável combina os registros à esquerda [2A, 6B] e os registros à direita [2C, 5D], comparando apenas as chaves numéricas. Qual é a ordem dos registros intercalados?
  1. 2C, 2A, 5D, 6B
  2. 2A, 5D, 2C, 6B
  3. 2A, 2C, 5D, 6B
  4. 2A, 2C, 6B, 5D
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 4: Analisar rastreamentos e justificar decisões10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Uma busca linear padrão faz 4 comparações em [14, 6, 21, 6]. Se ela para imediatamente na primeira correspondência, qual par de valor procurado e resultado é possível?
  1. Valor procurado 6, retornado 3
  2. Valor procurado 21, retornado 2
  3. Valor procurado 8, retorno -1
  4. Valor procurado 14, retornado 0
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma busca binária inclusiva tem limites low = 6, high = 6, e o elemento restante é igual ao valor procurado. O que o laço correto faz?
  1. Verifica o índice 6 e retorna 6
  2. Retorna -1 sem verificar
  3. Muda o limite inferior para 7 antes de verificar
  4. Verifica o índice 5 e retorna 5
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Quantas inversões há em [5, 3, 5, 2, 4, 1]?
  1. 10
  2. 11
  3. 12
  4. 15
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

A ordenação por seleção usa < estrito ao encontrar cada mínimo. Qual é a ordem final dos registros em [7A, 3X, 7B, 2Y, 3Z], comparando apenas as chaves numéricas?
  1. 2Y, 3Z, 3X, 7A, 7B
  2. 2Y, 3X, 3Z, 7B, 7A
  3. 2Y, 3Z, 3X, 7B, 7A
  4. 2Y, 3X, 3Z, 7A, 7B
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Use a ordenação por intercalação com divisões pela metade arredondadas para baixo em [9, 1, 7, 3]. Contando apenas comparações de elementos nas intercalações, quantas a ordenação completa faz?
  1. 2
  2. 3
  3. 4
  4. 5
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Um algoritmo primeiro compara cada par distinto uma vez e depois percorre todos os n elementos uma vez, contando uma comparação por elemento percorrido. Qual fórmula se aplica ao total de comparações?
  1. n(n−1)/2
  2. n(n+1)/2
  3. n2+n
  4. n(n−1)
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Um processo tenta todas as seleções de n elementos independentes, totalizando 2n seleções. O que acontece com essa contagem quando mais um elemento é acrescentado?
  1. Ela aumenta em um.
  2. Ela é elevada ao quadrado.
  3. Ela dobra.
  4. Ela quadruplica.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Execuções repetidas com tamanhos de entrada que dobram levam cerca de 0,06, 0,24 e 0,96 segundos. Qual padrão de crescimento essas razões sustentam?
  1. Crescimento quadrático
  2. Crescimento linear
  3. Crescimento constante
  4. Crescimento logarítmico
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma demonstração mostra que um laço de ordenação para com todos os pares de vizinhos em ordem. Seu código também sobrescreve algumas entradas sem salvá-las. Que propriedade adicional deve ser estabelecida antes de considerar a ordenação correta?
  1. Cada passada usa menos comparações.
  2. Cada elemento original mantém sua contagem.
  3. Cada chave igual mantém sua posição anterior.
  4. Cada execução usa memória extra fixa.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Um teste aleatório encontra uma falha de ordenação em uma lista longa. Qual próximo passo melhor ajuda a identificar o erro e evitar seu retorno?
  1. Manter a lista completa e rastrear repetidamente cada posição.
  2. Substituir a entrada por uma lista típica e guardar seu resultado.
  3. Gerar mais listas aleatórias antes de examinar a primeira falha.
  4. Reduzir a entrada que falha e mantê-la como teste de regressão.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Travou em uma questão sua? Ajuda com Tarefas

Termos-Chave

62 Termos-Chave, cada um com sua definição

A

Acesso direto
Acesso direto significa alcançar um elemento pelo seu índice sem percorrer os elementos anteriores, como permite um array ou uma lista Python.
Seguir enlaces até o meio de uma lista encadeada exige um percurso adicional, reduzindo a vantagem da busca binária.

B

Busca
Uma busca verifica se um valor procurado aparece em uma coleção e pode informar sua posição ou um resultado que indique sua ausência.
Uma busca em uma lista de identificadores de registros pode retornar a posição do registro solicitado sem alterar a lista.
Busca binária
Uma busca binária usa a ordem da lista para reduzir um intervalo inclusivo de posições candidatas, comparando o valor procurado com um elemento central.
Buscar em um array ordenado de cerca de um milhão de elementos exige no máximo 20 verificações de elementos centrais.
Busca linear (busca sequencial)
Uma busca linear verifica os elementos sequencialmente desde o início, parando na primeira correspondência ou informando a ausência após percorrer toda a lista.
Encontrar o último elemento de uma lista de nove elementos por busca linear exige nove comparações entre elemento e valor procurado.

C

Caso base
Um caso base é uma entrada tratada diretamente sem outra chamada recursiva, fornecendo um ponto de parada para a recursão.
Na ordenação por intercalação, tanto uma lista vazia quanto uma lista de um elemento são retornadas sem alteração porque já estão ordenadas.
Caso médio
O caso médio descreve o trabalho médio segundo uma distribuição especificada de entradas, portanto seu valor depende de quais entradas ocorrem.
Probabilidades iguais para as posições de valores procurados encontrados dão à busca linear uma média de (n+1)/2 comparações.
Caso recursivo
Um caso recursivo reduz o problema atual a instâncias menores e usa seus resultados para construir a resposta.
O caso recursivo da ordenação por intercalação ordena duas metades antes de chamar a intercalação com as listas ordenadas retornadas.
Caso-limite
Um caso-limite é uma entrada válida em um limite do comportamento de um algoritmo, onde limites de laço ou tratamentos especiais podem falhar.
Uma lista vazia verifica se a busca binária testa seus limites antes de tentar acessar um elemento central.
Chave de ordenação
Uma chave de ordenação é o valor ou campo de registro usado para determinar a ordem; o restante do registro permanece associado à chave quando o elemento se move.
Ordenar registros de cidades por população move cada nome de cidade junto com seu valor de população.
Compromisso entre critérios
Um compromisso entre critérios é uma escolha em que melhorar uma propriedade útil pode prejudicar outra, como economizar comparações usando mais memória.
A ordenação por intercalação melhora o crescimento do tempo para entradas grandes, mas geralmente precisa de mais armazenamento temporário que a ordenação por seleção.
Contraexemplo
Um contraexemplo é uma entrada válida cujo comportamento observado viola uma propriedade geral afirmada, refutando essa afirmação.
Uma única lista ordenada de dois elementos que causa uma busca infinita refuta a afirmação de que a busca sempre termina.
Crescimento constante
Crescimento constante significa que o trabalho contado permanece limitado independentemente do tamanho da entrada, como na leitura de uma posição conhecida de um array.
Consultar um índice especificado não exige percorrer cada elemento anterior do array à medida que a lista cresce.
Crescimento exponencial
O crescimento exponencial multiplica o trabalho por um fator fixo para cada elemento extra; uma contagem de 2n dobra quando um elemento é acrescentado.
Tentar todas as seleções de 30 elementos exige o dobro de seleções que tentar todas as seleções de 29.
Crescimento linear
Crescimento linear significa que o trabalho aumenta em proporção direta ao tamanho da entrada, de modo que dobrar o número de elementos aproximadamente dobra o trabalho.
Uma varredura completa com uma comparação de chaves por elemento faz 2.000 comparações quando sua entrada cresce para 2.000 elementos.
Crescimento logarítmico
O crescimento logarítmico ocorre quando uma redução repetida por um fator fixo faz cada duplicação da entrada acrescentar apenas uma quantidade fixa de trabalho.
Divisões sucessivas pela metade dão à busca binária cerca de uma verificação central extra cada vez que o tamanho da lista dobra.
Crescimento quadrático
Crescimento quadrático significa que o trabalho cresce em proporção ao quadrado do tamanho da entrada, produzindo cerca de quatro vezes mais trabalho quando ela dobra.
A contagem de comparações por pares da ordenação por seleção cresce quadraticamente, embora sua contagem de trocas cresça muito mais lentamente.
Custo de preparação
Um custo de preparação é o trabalho necessário antes da operação principal, como ordenar uma lista para que buscas binárias posteriores sejam válidas.
Uma única consulta pode favorecer uma varredura linear porque seu plano evita um grande custo de ordenação feito uma única vez.

D

Divisão e conquista
A divisão e conquista resolve um problema dividindo-o em problemas menores, resolvendo-os e combinando seus resultados.
A ordenação por intercalação combina resultados de metades ordenadas; a divisão, por si só, deixa inalterada a ordem original dos valores.

E

Elementos adjacentes
Elementos adjacentes ocupam posições vizinhas em uma lista, portanto seus índices diferem exatamente em uma unidade quando ambas as posições existem.
A ordenação por bolha compara items[j] com items[j + 1], fazendo sua movimentação depender de pares de vizinhos.
Erro de uma unidade
Um erro de uma unidade faz um limite de laço ou índice incluir uma posição a mais ou a menos, causando uma omissão ou um acesso inválido.
Usar low < high para um intervalo binário inclusivo ignora um candidato final quando os extremos se tornam iguais.
Especificação
Uma especificação estabelece os requisitos para entradas válidas e o resultado que um algoritmo deve produzir, permitindo verificar sua correção.
Uma especificação de busca distingue um índice correspondente de um resultado especial usado somente quando não há correspondência.
Estouro de inteiro
O estouro de inteiro ocorre quando uma operação aritmética ultrapassa a faixa de um inteiro de largura fixa; o efeito depende da linguagem e da operação.
Uma posição central calculada pela diferença evita uma soma excessiva dos extremos quando os índices são não negativos e válidos.

Í

Índice
Um índice é uma posição numerada usada para acessar um elemento de uma lista; os índices em Python começam em zero e terminam uma unidade antes do comprimento da lista.
Em [8, 13, 21], o índice 2 contém 21, embora seja o terceiro elemento na contagem cotidiana.

I

Intercalação
Uma intercalação combina duas listas ordenadas copiando repetidamente o menor elemento à frente ainda não utilizado e depois copiando o trecho restante.
Intercalar [3, 10] e [6, 12] produz [3, 6, 10, 12] sem ordenar novamente nenhuma das entradas.
Intervalo de posições candidatas
Um intervalo de posições candidatas é o intervalo de posições que ainda podem conter um valor procurado depois que comparações anteriores descartaram as demais.
Os limites de 4 a 7 incluem quatro posições candidatas, e os limites de 5 a 4 descrevem um intervalo vazio.
Invariante de laço
Um invariante de laço é uma afirmação verdadeira antes do início do laço e preservada após cada repetição, sustentando um argumento sobre o resultado.
O invariante da ordenação por seleção relaciona o comprimento de seu prefixo aos menores elementos que já foram posicionados.
Inversão
Uma inversão é um par de posições em que um elemento anterior tem chave maior que a de um elemento posterior; chaves iguais não contribuem com inversões.
Em [8, 3, 6], 8 forma uma inversão com cada um dos dois valores posteriores, embora apenas um dos pares seja adjacente.

L

Limite de tempo de execução
Um limite de tempo de execução é o tempo permitido, usado com um modelo de custo para estimar o tamanho de entrada que pode ser processado.
Um processo quadrático pode processar uma entrada três vezes maior quando o tempo disponível aumenta por um fator de nove.

M

Marcador de posição
Um marcador de posição acompanha a próxima posição não utilizada em uma lista de entrada para que uma intercalação saiba qual elemento comparar ou copiar em seguida.
Marcadores separados à esquerda e à direita impedem que uma intercalação copie um elemento duas vezes ou ignore um após uma comparação.
Melhor caso
O melhor caso é a situação de entrada válida que exige o menor número de operações contadas entre entradas do mesmo tamanho.
Uma busca linear que encontra o valor procurado na primeira posição faz uma comparação em uma lista não vazia.

O

Operação básica
Uma operação básica é a ação repetida escolhida para contar o trabalho, como comparar duas chaves ou verificar um elemento central.
Uma verificação binária de elemento central pode realizar duas comparações de elementos, portanto sua contagem de verificações precisa ser identificada separadamente.
Ordenação
A ordenação reorganiza elementos na ordem de suas chaves, preservando cada elemento original e cada ocorrência repetida.
Um resultado crescente que perde uma duplicata não é uma ordenação correta, mesmo que todos os vizinhos estejam em ordem.
Ordenação estável
Uma ordenação estável preserva a ordem relativa original dos registros cujas chaves são iguais na comparação, mesmo quando outros registros se movem.
Uma ordenação estável por nota mantém nomes em ordem alfabética dentro de cada grupo de notas se eles já estavam nessa ordem.
Ordenação no próprio local
Uma ordenação no próprio local reorganiza a lista existente usando apenas uma quantidade fixa de armazenamento extra de trabalho à medida que o tamanho da entrada cresce.
A ordenação por bolha precisa de alguns contadores e de um indicador de troca em vez de outra lista proporcional à entrada.
Ordenação por intercalação
A ordenação por intercalação ordena recursivamente duas metades menores e intercala os resultados ordenados, produzindo crescimento de trabalho proporcional a nlog⁡n.
Uma lista grande passa por vários tamanhos de divisão antes de suas partes ordenadas serem reconstruídas em uma única saída.
Ordenação por seleção
A ordenação por seleção percorre repetidamente a parte não ordenada em busca de seu mínimo e troca esse elemento para a próxima posição de um prefixo ordenado.
Uma varredura da ordenação por seleção guarda o índice do menor elemento antes de fazer sua única troca possível que move elementos.

P

Parada antecipada
Uma parada antecipada encerra um algoritmo antes de seu trabalho máximo previsto quando uma condição verificada estabelece o resultado exigido.
Uma passada sem trocas da ordenação por bolha confirma a ordem; as comparações dessa passada ainda contam para o total.
Passada
Uma passada é um percurso pela parte ativa de uma lista que realiza uma sequência de comparações ou posicionamentos.
Uma passada da ordenação por bolha posiciona o maior elemento restante, mas pode deixar as posições anteriores não ordenadas.
Permutação
Uma permutação é um rearranjo dos mesmos elementos que preserva o número de ocorrências de cada valor.
[2, 8, 2] e [2, 2, 8] são permutações uma da outra; [2, 8] perde uma ocorrência.
Pior caso
O pior caso é a situação de entrada válida que exige o maior número de operações contadas entre entradas do mesmo tamanho.
Um valor procurado ausente obriga a busca linear básica a inspecionar todas as posições, produzindo sua contagem no pior caso.
Ponto de cruzamento
Um ponto de cruzamento é um tamanho de entrada em que dois modelos de custo empatam e além do qual sua ordem pode mudar à medida que a entrada cresce.
Os modelos 40n e n2 empatam em 40 elementos; o modelo linear se torna menos custoso para tamanhos positivos maiores.
Pós-condição
Uma pós-condição estabelece o que deve ser verdadeiro sobre o resultado de um algoritmo quando ele termina com uma entrada que atende à sua pré-condição.
Uma pós-condição de ordenação inclui tanto chaves em ordem quanto a preservação das ocorrências originais.
Posição central
Uma posição central é a posição do meio escolhida em um intervalo de busca, arredondada para baixo quando a média dos extremos não é um número inteiro.
Para os limites inclusivos 2 e 7, (2 + 7) // 2 seleciona o índice 4 como a próxima posição central.
Pré-condição
Uma pré-condição é um requisito que deve valer para uma entrada antes que o comportamento prometido de um algoritmo seja garantido.
A ordem crescente é uma pré-condição da busca binária comum, portanto uma entrada não ordenada invalida seu raciocínio sobre intervalos.
Prefixo ordenado
Um prefixo ordenado é uma parte inicial de uma lista que já está em ordem; a ordenação por seleção o preenche primeiro com os menores elementos.
Após três passadas da ordenação por seleção, as três primeiras posições contêm os três menores elementos em ordem.
Previsão do tempo de execução
Uma previsão do tempo de execução estima o tempo em outro tamanho aplicando um modelo de crescimento a um tempo de referência medido ou fornecido.
Triplicar a entrada em um modelo quadrático multiplica o tempo de referência por cerca de nove, não três.
Primeiro elemento ainda não utilizado
O primeiro elemento ainda não utilizado em uma intercalação é o elemento à frente de uma entrada ordenada e, portanto, seu menor elemento restante.
Após escolher o elemento à frente da esquerda, avance apenas o marcador da esquerda; o elemento à frente da direita ainda aguarda comparação.

R

Recursão
A recursão resolve um problema por meio de chamadas ao mesmo procedimento para instâncias menores, com uma regra de parada para casos simples.
A ordenação por intercalação chama a si mesma para cada metade menor até que uma chamada receba no máximo um elemento.
Rotina de ordenação de biblioteca
Uma rotina de ordenação de biblioteca é uma implementação de ordenação testada de uma linguagem ou biblioteca, com comportamento documentado, como estabilidade e forma da saída.
sorted do Python cria uma nova lista de resultados, enquanto list.sort() reorganiza a lista existente.

S

Sufixo não ordenado
Um sufixo não ordenado é a parte final restante cuja ordem interna ainda não foi estabelecida pelo processo de ordenação.
A ordenação por seleção busca apenas no sufixo não ordenado para não selecionar novamente um mínimo já posicionado.

T

Tamanho da entrada
O tamanho da entrada mede a quantidade de dados que um algoritmo recebe; para os algoritmos de listas apresentados aqui, é o número de elementos, n.
Duas listas de mesmo comprimento têm o mesmo tamanho de entrada, mesmo que uma esteja ordenada e a outra em ordem inversa.
Taxa de crescimento
Uma taxa de crescimento descreve como o trabalho de um algoritmo muda com o tamanho da entrada, distinguindo seu padrão de escala de uma única execução.
Um tempo baixo em um tamanho pequeno deixa em aberto a rapidez com que esse tempo aumenta quando os dados ficam muito maiores.
Tempo de execução de referência
Um tempo de execução de referência é um tempo medido para um tamanho de entrada conhecido, usado como ponto de partida para uma estimativa baseada no tamanho.
Um tempo de referência de 4 segundos para 20.000 elementos pode sustentar uma estimativa quadrática para uma execução comparável maior.
Terminação
A terminação significa que a execução acaba parando; uma medida inteira não negativa que diminui pode estabelecê-la para um laço.
Excluir a posição central testada faz a contagem de candidatos da busca binária diminuir estritamente após cada não correspondência.
Termo dominante
Um termo dominante é a parte de crescimento mais rápido de uma expressão de contagem de passos, que determina seu crescimento a longo prazo à medida que o tamanho da entrada aumenta.
Em n2/2−n/2, o termo quadrático domina, embora ambos os termos afetem uma contagem exata de comparações.
Teste aleatório
O teste aleatório gera entradas variadas e verifica os resultados com base em uma especificação ou em um método confiável para procurar falhas inesperadas.
Comparar muitas saídas de ordenação geradas aleatoriamente com sorted pode revelar um caso não detectado por testes escolhidos manualmente.
Teste de duplicação do tamanho da entrada
Um teste de duplicação do tamanho da entrada compara custos em tamanhos sucessivos que dobram para procurar as razões associadas às famílias de crescimento.
Razões de tempo repetidas próximas de quatro sugerem crescimento quadrático no intervalo de tamanhos medido.
Teste de regressão
Um teste de regressão mantém uma verificação de um comportamento anteriormente correto ou corrigido para que alterações posteriores revelem o retorno de uma falha.
Mantenha uma lista mínima que já causou a perda de uma duplicata para verificar se alterações futuras preservam todas as cópias.
Trecho restante
Um trecho restante é a parte de uma lista a partir de uma posição escolhida, copiada diretamente quando a outra entrada da intercalação se esgota.
Se uma entrada da intercalação se esgotar enquanto [14, 20] permanece do outro lado, os dois elementos do trecho restante ainda são necessários.
Troca
Uma troca permuta dois elementos armazenados preservando os dois valores originais, por meio de um valor guardado ou de uma atribuição simultânea.
Sem guardar um valor, duas atribuições sucessivas podem transformar [2, 9] em [9, 9] em vez de trocar os elementos.

V

Valor procurado
O valor procurado é o valor buscado, comparado com os elementos armazenados ou com um campo escolhido de cada registro armazenado.
Em uma busca pelo identificador 630, o valor procurado é 630; a posição retornada é outro número.
Varredura completa
Uma varredura completa inspeciona cada elemento de uma coleção, como é necessário ao contar todas as correspondências ou encontrar o maior valor.
Contar todas as ocorrências de 7 continua após a primeira correspondência porque elementos posteriores também podem conter 7.

Sobre esta aula

Por StudeliRelatar um erro

Crie seus próprios Materiais de Estudo

Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.

Começar