Capitulo 14 - Algoritmos de Pesquisa e Ordenação

[1]Copyright © 2026 Alyce Suza.

Fundamentos de organização e recuperação eficiente de dados em memória

14.1 A Necessidade de Organização da Informação

A capacidade de armazenar grandes volumes de informação em vetores e matrizes resolve apenas a primeira metade do problema no processamento computacional. A segunda metade consiste em recuperar um dado específico no meio de milhares de registos e em apresentar essa informação de forma estruturada ao utilizador. A ciência da computação dedica um ramo inteiro ao estudo de algoritmos de pesquisa e ordenação, avaliando o custo matemático e o consumo de recursos que cada abordagem exige do processador. A escolha do algoritmo correto determina se uma aplicação encontra um registo numa fração de milissegundo ou se o sistema congela durante vários minutos ao processar uma base de dados extensa.

Knuth (1997) "Praticamente todos os sistemas informáticos importantes passam uma parte considerável do seu tempo de processamento a ordenar e a pesquisar dados. A otimização destas operações constitui um dos pilares centrais da eficiência algorítmica."

Donald E. Knuth, The Art of Computer Programming. Vol. 3: Sorting and Searching. 2. ed. Addison-Wesley, 1997.

14.2 Algoritmos de Pesquisa Sequencial

A pesquisa sequencial representa o método mais rudimentar e direto para localizar um elemento dentro de um vetor. O algoritmo baseia-se na travessia linear da estrutura de dados, avaliando cada posição individual desde o índice zero até ao limite final do array. A cada iteração, o processador compara o elemento alojado na memória com o valor alvo procurado. Se a verificação resultar verdadeira, a função interrompe a sua execução e devolve o índice exato onde o dado foi localizado. Caso o laço de repetição atinja o fim do vetor sem encontrar correspondência, o algoritmo devolve um valor negativo padrão, tipicamente o menos um, sinalizando formalmente a ausência do registo no sistema.

Esta abordagem possui a vantagem arquitetural de funcionar em qualquer coleção de dados, independentemente da sua desordem interna. O custo de processamento, no entanto, escala de forma linear e proporcional ao tamanho do vetor. Num cenário pessimista onde o elemento não existe ou se encontra na última posição de um array com um milhão de registos, o processador será forçado a executar um milhão de operações de comparação redundantes.

programa
{
    funcao inteiro pesquisaSequencial(inteiro lista[], inteiro tamanho, inteiro alvo)
    {
        para (inteiro i = 0; i < tamanho; i++)
        {
            se (lista[i] == alvo)
            {
                retorne i
            }
        }
        retorne -1
    }

    funcao inicio()
    {
        inteiro baseDados[] = {45, 12, 89, 33, 76, 21}
        inteiro procurar = 33
        inteiro posicao
        
        posicao = pesquisaSequencial(baseDados, 6, procurar)
        
        se (posicao != -1)
        {
            escreva("Registo localizado com sucesso no indice: ", posicao, "\n")
        }
        senao
        {
            escreva("Falha na operacao: O registo nao existe na base de dados.\n")
        }
    }
}

14.3 Algoritmos de Ordenação e o Método Bolha

A organização estruturada dos dados viabiliza a implementação de algoritmos de pesquisa imensamente mais rápidos, além de garantir a apresentação de relatórios legíveis para interpretação humana. Existem dezenas de métodos matemáticos para ordenar vetores, variando drasticamente na sua complexidade e eficiência. O Método Bolha, conhecido tecnicamente como Bubble Sort, constitui a técnica introdutória padrão no ensino de programação devido à sua lógica intuitiva, apesar de ser inadequado para bases de dados de escala industrial.

A mecânica do Método Bolha assenta em múltiplas passagens sucessivas pelo vetor. O algoritmo varre a estrutura comparando elementos adjacentes em pares. Se o elemento da esquerda for estritamente maior do que o elemento da direita, o sistema executa a troca física das suas posições utilizando uma variável auxiliar de memória. Este processo empurra iterativamente os maiores valores para o final do vetor, simulando o comportamento físico de bolhas a subir para a superfície de um líquido. A ordenação é dada como concluída quando o algoritmo realiza uma passagem completa pela estrutura sem efetuar qualquer permuta entre os elementos.

programa
{
    funcao vazio ordenacaoBolha(inteiro lista[], inteiro tamanho)
    {
        inteiro memoriaAuxiliar
        
        para (inteiro i = 0; i < tamanho - 1; i++)
        {
            para (inteiro j = 0; j < tamanho - 1 - i; j++)
            {
                se (lista[j] > lista[j+1])
                {
                    memoriaAuxiliar = lista[j]
                    lista[j] = lista[j+1]
                    lista[j+1] = memoriaAuxiliar
                }
            }
        }
    }

    funcao inicio()
    {
        inteiro amostra[] = {8, 3, 15, 2, 9, 4}
        
        escreva("Estado bruto do vetor: ")
        para (inteiro i = 0; i < 6; i++) { escreva(amostra[i], " ") }
        
        ordenacaoBolha(amostra, 6)
        
        escreva("\nEstado ordenado do vetor: ")
        para (inteiro i = 0; i < 6; i++) { escreva(amostra[i], " ") }
        escreva("\n")
    }
}

14.4 Pesquisa Binária e Eficiência Logarítmica

Quando um vetor se encontra rigorosamente ordenado, a utilização da pesquisa sequencial torna-se num desperdício matemático injustificável. O algoritmo de Pesquisa Binária explora a ordenação prévia para aplicar a estratégia de divisão e conquista, reduzindo exponencialmente o espaço de busca a cada iteração. O sistema estabelece dois ponteiros demarcando o limite inferior e o limite superior do segmento avaliado. A cada ciclo o processador calcula o índice central e compara o valor ali alojado com o alvo procurado.

Se o valor central for exatamente igual ao alvo, a pesquisa termina instantaneamente com sucesso. Se o alvo for menor do que o valor central, o algoritmo conclui logicamente que o elemento só pode residir na metade esquerda do vetor, descartando a metade direita inteira da memória numa única operação ao ajustar o limite superior. O processo repete-se dividindo a estrutura consecutivamente até encontrar o registo ou até que os limites se cruzem. Esta arquitetura garante uma eficiência logarítmica imbatível. Num vetor com um milhão de elementos ordenados, a pesquisa binária requereria um máximo absoluto de vinte comparações matemáticas para localizar o dado ou atestar a sua ausência.

programa
{
    funcao inteiro pesquisaBinaria(inteiro lista[], inteiro tamanho, inteiro alvo)
    {
        inteiro limiteInferior = 0
        inteiro limiteSuperior = tamanho - 1
        inteiro pontoCentral
        
        enquanto (limiteInferior <= limiteSuperior)
        {
            pontoCentral = (limiteInferior + limiteSuperior) / 2
            
            se (lista[pontoCentral] == alvo)
            {
                retorne pontoCentral
            }
            senao se (lista[pontoCentral] < alvo)
            {
                limiteInferior = pontoCentral + 1
            }
            senao
            {
                limiteSuperior = pontoCentral - 1
            }
        }
        retorne -1
    }

    funcao inicio()
    {
        // O algoritmo exige rigorosamente que a estrutura nasca ordenada
        inteiro codigosValidos[] = {102, 245, 388, 412, 599, 670, 891}
        inteiro consulta = 599
        
        inteiro resultado = pesquisaBinaria(codigosValidos, 7, consulta)
        
        se (resultado >= 0)
        {
            escreva("Codigo verificado e validado na posicao de memoria: ", resultado, "\n")
        }
        senao
        {
            escreva("Alerta: O codigo fornecido nao consta no registo do sistema.\n")
        }
    }
}

14.5 Exercícios do Capítulo 14

Exercício 14.1: Contagem de Ocorrências com Pesquisa Sequencial Declare um vetor de tamanho dez contendo múltiplos valores repetidos no seu interior.

Construa uma função que receba este vetor e um número alvo específico por parâmetro. O subprograma deve aplicar a técnica da pesquisa sequencial para percorrer a estrutura completa, atuando em conjunto com um acumulador simples para contabilizar quantas vezes exatas o valor alvo aparece alojado no array. A função deve devolver o total absoluto desta contagem ao bloco principal.

Exercício 14.2: Ordenação Decrescente de Notas Académicas Programe um vetor real capaz de alojar as notas finais de oito alunos submetidos a exame.

Altere a estrutura condicional interna do algoritmo Método Bolha para forçar a reorganização dos dados em formato estritamente decrescente, garantindo que as notas mais elevadas assumam os índices iniciais do vetor. Imprima a listagem académica completa após a consolidação da permutação.

Exercício 14.3: Integração de Ordenação e Pesquisa Binária Leia cinco valores inteiros aleatórios fornecidos pelo utilizador e guarde os dados num vetor.

Aplique obrigatoriamente a função de ordenação para organizar os valores em ordem crescente antes de qualquer outra operação. Em seguida, solicite ao utilizador um número para consulta e execute exclusivamente a pesquisa binária para localizar e informar em que posição definitiva o número se encontra acomodado após o processo de ordenação estrutural.

Gabarito do Capítulo 14

Gabarito do Exercício 14.1 A adaptação da pesquisa sequencial para contabilizar multiplicidade requer a eliminação do comando de retorno imediato. Em vez de interromper o ciclo ao encontrar a primeira correspondência, o algoritmo deve atualizar ativamente um contador interno e permitir que a varredura atinja o limite final da matriz, devolvendo apenas a somatória estática no encerramento.

programa
{
    funcao inteiro contarOcorrencias(inteiro lista[], inteiro tamanho, inteiro alvo)
    {
        inteiro contador = 0
        para (inteiro i = 0; i < tamanho; i++)
        {
            se (lista[i] == alvo)
            {
                contador++
            }
        }
        retorne contador
    }
    
    funcao inicio()
    {
        inteiro registos[] = {4, 7, 2, 4, 9, 4, 1, 8, 4, 5}
        inteiro procura = 4
        inteiro total
        
        total = contarOcorrencias(registos, 10, procura)
        escreva("Deteccao completa: O alvo ", procura, " surge ", total, " vezes na rede de dados.\n")
    }
}

Gabarito do Exercício 14.2 A alteração do fluxo ascendente para o fluxo descendente no Método Bolha consiste na inversão cirúrgica de um único operador relacional. Ao substituir a exigência matemática do operador maior para o operador menor durante a avaliação do par adjacente, o algoritmo empurra automaticamente os valores ínfimos para a cauda da estrutura.

programa
{
    funcao vazio ordenacaoDescendente(real avaliacoes[], inteiro volume)
    {
        real baseTemporaria
        para (inteiro i = 0; i < volume - 1; i++)
        {
            para (inteiro j = 0; j < volume - 1 - i; j++)
            {
                se (avaliacoes[j] < avaliacoes[j+1])
                {
                    baseTemporaria = avaliacoes[j]
                    avaliacoes[j] = avaliacoes[j+1]
                    avaliacoes[j+1] = baseTemporaria
                }
            }
        }
    }
    
    funcao inicio()
    {
        real pauta[] = {6.5, 9.0, 4.5, 8.5, 7.0, 10.0, 5.5, 8.0}
        
        ordenacaoDescendente(pauta, 8)
        
        escreva("Pauta letiva compilada por ordem de merito academico:\n")
        para (inteiro k = 0; k < 8; k++)
        {
            escreva(k + 1, "o Lugar: ", pauta[k], " valores\n")
        }
    }
}

Gabarito do Exercício 14.3 A integração fluida entre as duas ferramentas consolida o paradigma da arquitetura modular. A pesquisa binária exige a garantia matemática de que a base de dados submetida ao seu escrutínio esteja imaculadamente classificada, e o acoplamento do algoritmo de permutação previamente à chamada de consulta sela a robustez do programa, blindando-o contra falhas lógicas decorrentes de desordem inserida pelo utilizador.

programa
{
    funcao vazio ordenarElementos(inteiro v[], inteiro n)
    {
        inteiro aux
        para (inteiro i = 0; i < n - 1; i++)
        {
            para (inteiro j = 0; j < n - 1 - i; j++)
            {
                se (v[j] > v[j+1])
                {
                    aux = v[j]
                    v[j] = v[j+1]
                    v[j+1] = aux
                }
            }
        }
    }
    
    funcao inteiro buscarBinario(inteiro v[], inteiro n, inteiro alvo)
    {
        inteiro esq = 0, dir = n - 1, meio
        enquanto (esq <= dir)
        {
            meio = (esq + dir) / 2
            se (v[meio] == alvo) { retorne meio }
            senao se (v[meio] < alvo) { esq = meio + 1 }
            senao { dir = meio - 1 }
        }
        retorne -1
    }
    
    funcao inicio()
    {
        inteiro vetor[5], busca, id
        
        para (inteiro i = 0; i < 5; i++)
        {
            escreva("Preencha a ranhura de memoria ", i, ": ")
            leia(vetor[i])
        }
        
        ordenarElementos(vetor, 5)
        
        escreva("\nProcesso de indexacao finalizado. Base de dados pronta.\n")
        escreva("Indique o elemento a extrair da memoria: ")
        leia(busca)
        
        id = buscarBinario(vetor, 5, busca)
        
        se (id != -1)
        {
            escreva("Elemento capturado e lido no indice oficial: ", id, "\n")
        }
        senao
        {
            escreva("Elemento rejeitado pelo subsistema de procura profunda.\n")
        }
    }
}


  1. Copyright © 2026 Alyce Suza. Todos os direitos reservados nos termos da Lei 9.610/98. O conteúdo publicado no site https://wiki.suzacybersecurity.com/ é protegido pelas diretrizes brasileiras de propriedade intelectual e a sua autoria é reconhecida desde o momento da criação técnica. O compartilhamento, a reprodução e a distribuição deste material são permitidos e incentivados apenas para finalidades educacionais, acadêmicas ou de consulta técnica, sendo estritamente vedado qualquer tipo de uso comercial. Para que a replicação seja validada e legal, você deve obrigatoriamente atribuir os devidos créditos a Alyce Suza e fornecer um link direto e acessível para a publicação original. A utilização deste material para obter lucro, monetização, venda de materiais ou qualquer vantagem financeira constitui violação de direitos autorais e está sujeita às sanções legais cabíveis, assim como alterações que modifiquem o sentido original das explicações sobre segurança da informação. Para eventuais dúvidas sobre permissões de uso, parcerias ou para reportar replicações indevidas, envie um e-mail para alycesuza@gmail.com. ↩︎