📚 Capítulo do curso: 10 — Vetores 1D (Arrays), Memória e Algoritmos de Busca/Ordenação da Especialização em Sistemas com C. Leia o capítulo antes de começar.
Ordena um vetor com Bubble Sort e mede, na prática, quantas comparações a Busca Binária economiza em relação à Busca Linear.
🔗 Conectando com o Miniprojeto 07: lá você implementou um crivo de primos “na unha”, testando cada número individualmente porque ainda não existiam vetores. Agora, com arrays de verdade liberados pelo Capítulo 10, o Desafio de Extensão deste projeto te convida a voltar e reescrever aquele crivo como um Crivo de Eratóstenes real, marcando múltiplos num vetor — a diferença de desempenho entre força bruta e crivo é brutal.
| ⏱️ Tempo estimado | 📦 Você vai entregar | ✅ Pronto quando |
|---|---|---|
| 60 min | main.c |
o vetor sai ordenado, 63 é achado no índice 7 com 2 comparações |
array de inteiros.int vetor[]), fixando a diferença entre percorrer um array por índice e as demais formas de acesso que você verá em capítulos futuros.Você está construindo o núcleo de um motor de busca simplificado. Ele recebe um array fixo de pelo menos 10 números inteiros desordenados e precisa: ordená-los para permitir buscas eficientes, localizar um valor específico usando Busca Binária, e provar — com números reais — por que vale a pena pagar o custo de ordenar antes de buscar repetidamente.
O programa (main.c) deve:
N) e da Busca Binária (≈ log2(N) + 1), evidenciando por que a busca binária escala muito melhor à medida que N cresce.| ID | Requisito |
|---|---|
| RF01 | O programa deve compilar sem nenhum aviso com gcc -Wall -Wextra -Wpedantic -std=c17. |
| RF02 | Deve declarar um array de pelo menos 10 int desordenados, sem usar ponteiros nem malloc. |
| RF03 | Deve implementar ordenar_bubble_sort, que ordena o array em ordem crescente, recebendo-o como parâmetro de função. |
| RF04 | Deve implementar busca_binaria, que retorna o índice do valor procurado (ou -1 se não encontrado), operando apenas sobre o array já ordenado. |
| RF05 | Deve contar e imprimir quantas comparações a Busca Binária realmente fez para encontrar o valor, e comparar esse número com o pior caso teórico da Busca Linear (N comparações) e da própria Busca Binária (≈ log2(N)). |
graph LR
A["Vetor desordenado\n(10+ inteiros)"] --> B["ordenar_bubble_sort()"]
B --> C["Vetor ordenado"]
C --> D["busca_binaria()\ne contagem de comparacoes"]
D --> E["Relatorio:\nBinaria vs Linear\n(pior caso)"]
style B fill:#0284c7,stroke:#38bdf8,color:#ffffff
style D fill:#0d9488,stroke:#2dd4bf,color:#ffffff
style E fill:#059669,stroke:#34d399,color:#ffffff
O mesmo do Miniprojeto 01: gcc 8 ou mais novo. No Windows, rode chcp 65001 se os emojis aparecerem quebrados.
🎯 Objetivo: partir de um código que compila e roda, antes de escrever qualquer linha.
⌨️ Faça: crie a pasta c_mini_10, salve o código abaixo como main.c e rode:
gcc -Wall -Wextra -Wpedantic -std=c17 main.c -o app
./app # Linux/macOS
.\app.exe # Windows (PowerShell)
📄 src/esqueleto.c
/*
* Miniprojeto 10: Motor de Busca Binaria e Benchmark de Ordenacao
* Capitulo 10: arrays, busca linear/binaria, ordenacao.
*/
#include <stdio.h>
#include <stdlib.h>
#define TAMANHO 10
void ordenar_bubble_sort(int vetor[], int tamanho) {
(void)vetor; (void)tamanho; // stub: apague esta linha ao implementar
// TODO 1: implemente o Bubble Sort classico com dois lacos aninhados.
// Dica: se uma passada inteira nao trocar nenhum par, o vetor ja esta
// ordenado (use uma flag "trocou" para interromper mais cedo).
}
void imprimir_vetor(const int vetor[], int tamanho) {
(void)vetor; (void)tamanho; // stub: apague esta linha ao implementar
// TODO 2: imprima o vetor no formato "[ v0 v1 v2 ... ]"
}
int busca_binaria(const int vetor[], int tamanho, int alvo) {
(void)vetor; (void)tamanho; (void)alvo; // stub: apague esta linha ao implementar
// TODO 3: implemente a busca binaria classica (inicio/fim/meio) e
// retorne o indice do elemento encontrado, ou -1 se nao encontrado.
return -1;
}
int contar_comparacoes_busca_binaria(const int vetor[], int tamanho, int alvo) {
(void)vetor; (void)tamanho; (void)alvo; // stub: apague esta linha ao implementar
// TODO 4: repita a logica da busca binaria, mas desta vez contando
// quantas vezes o valor do meio foi comparado com o alvo.
return 0;
}
int main(void) {
int numeros[TAMANHO] = {45, 12, 78, 3, 91, 27, 56, 8, 63, 34};
int alvo = 63;
printf("Valor a buscar: %d\n", alvo);
printf("Vetor original (desordenado): ");
imprimir_vetor(numeros, TAMANHO);
ordenar_bubble_sort(numeros, TAMANHO);
printf("Vetor ordenado (Bubble Sort): ");
imprimir_vetor(numeros, TAMANHO);
// TODO 5: chame busca_binaria e contar_comparacoes_busca_binaria,
// imprima o indice encontrado e o benchmark (linear vs binaria).
return EXIT_SUCCESS;
}
✅ Checkpoint: zero avisos do gcc, e a saída é:
🖥️ Saída esperada:
Valor a buscar: 63
Vetor original (desordenado): Vetor ordenado (Bubble Sort):
💡
(void)parametro;: as funções do esqueleto ainda são stubs (cascas vazias). Sem essas linhas, ogcc -Wextraavisariaunused parameter. Apague cada linha(void)...quando implementar a função correspondente.
As linhas Vetor original e Vetor ordenado saem vazias e coladas porque imprimir_vetor ainda não faz nada.
🎯 Objetivo: percorrer um array recebido como parâmetro (const int vetor[]).
⌨️ Faça: em imprimir_vetor, imprima [ , cada elemento seguido de espaço e ] com quebra de linha.
✅ Checkpoint: as duas linhas mostram [ 45 12 78 3 91 27 56 8 63 34 ]. Ainda são iguais, porque a ordenação não existe.
🧯 Se der errado: sizeof(vetor) dentro da função dá 8, não 40. Um array passado para função vira ponteiro, por isso o tamanho precisa vir como parâmetro.
🎯 Objetivo: ordenar no lugar, trocando vizinhos fora de ordem.
⌨️ Faça: dois for aninhados: o externo conta as passadas (i) e o interno compara vetor[j] com vetor[j + 1] até tamanho - 1 - i, trocando com uma variável temp. Use uma flag trocou e faça break se uma passada inteira não trocar nada.
✅ Checkpoint: Vetor ordenado (Bubble Sort): [ 3 8 12 27 34 45 56 63 78 91 ].
🧯 Se der errado: um número estranho aparece no vetor (lixo ou o 91 duplicado): o laço interno foi até j < tamanho e leu vetor[j + 1] fora do array.
🎯 Objetivo: dividir o espaço de busca pela metade a cada comparação.
⌨️ Faça:
busca_binaria: com inicio = 0 e fim = tamanho - 1, enquanto inicio <= fim, calcule meio = inicio + (fim - inicio) / 2. Se achou, devolva meio; senão, mova inicio ou fim. Ao sair do laço, devolva -1.contar_comparacoes_busca_binaria: a mesma lógica, incrementando um contador a cada meio examinado.main, imprima o índice encontrado e o benchmark: pior caso linear (N), pior caso binário e as comparações reais. Para o pior caso binário, conte quantas vezes é preciso dobrar 1 até alcançar N e some 1.✅ Checkpoint: Valor 63 encontrado no indice 7., pior caso linear 10, pior caso binário 5 e 2 comparações reais. O primeiro meio é o índice 4 (valor 34), e o segundo já é o 7.
🧯 Se der errado: o programa trava: inicio ou fim não estão mudando, por exemplo com inicio = meio em vez de meio + 1.
🎯 Objetivo: validar a saída completa e o código de retorno.
✅ Checkpoint: a saída é esta, e o código de retorno é 0 (echo $? no Linux/macOS ou echo $LASTEXITCODE no PowerShell):
🖥️ Saída esperada:
====================================================
⚡ Motor de Busca Binaria e Benchmark de Ordenacao
====================================================
Vetor original (desordenado): [ 45 12 78 3 91 27 56 8 63 34 ]
Vetor ordenado (Bubble Sort): [ 3 8 12 27 34 45 56 63 78 91 ]
----------------------------------------------------
Valor 63 encontrado no indice 7.
--- Benchmark de comparacoes (N = 10) ---
Busca Linear -> pior caso teorico: 10 comparacoes
Busca Binaria -> pior caso teorico: 5 comparacoes
Busca Binaria -> comparacoes reais nesta execucao: 2
====================================================
Só abra o gabarito depois de chegar até aqui:
src/main.c📄 src/main.c
/*
* Miniprojeto 10: Motor de Busca Binaria e Benchmark de Ordenacao
* Especializacao em Engenharia de Sistemas em C
* Capitulo 10: arrays, busca linear/binaria, algoritmos de ordenacao.
*/
#include <stdio.h>
#include <stdlib.h>
#define TAMANHO 10
void ordenar_bubble_sort(int vetor[], int tamanho) {
for (int i = 0; i < tamanho - 1; i++) {
int trocou = 0;
for (int j = 0; j < tamanho - 1 - i; j++) {
if (vetor[j] > vetor[j + 1]) {
int temp = vetor[j];
vetor[j] = vetor[j + 1];
vetor[j + 1] = temp;
trocou = 1;
}
}
if (!trocou) {
break;
}
}
}
void imprimir_vetor(const int vetor[], int tamanho) {
printf("[ ");
for (int i = 0; i < tamanho; i++) {
printf("%d ", vetor[i]);
}
printf("]\n");
}
int busca_binaria(const int vetor[], int tamanho, int alvo) {
int inicio = 0;
int fim = tamanho - 1;
while (inicio <= fim) {
int meio = inicio + (fim - inicio) / 2;
if (vetor[meio] == alvo) {
return meio;
}
if (vetor[meio] < alvo) {
inicio = meio + 1;
} else {
fim = meio - 1;
}
}
return -1;
}
int contar_comparacoes_busca_binaria(const int vetor[], int tamanho, int alvo) {
int inicio = 0;
int fim = tamanho - 1;
int comparacoes = 0;
while (inicio <= fim) {
int meio = inicio + (fim - inicio) / 2;
comparacoes++;
if (vetor[meio] == alvo) {
break;
}
if (vetor[meio] < alvo) {
inicio = meio + 1;
} else {
fim = meio - 1;
}
}
return comparacoes;
}
int comparacoes_pior_caso_binaria(int tamanho) {
int comparacoes = 0;
int alcance = 1;
while (alcance < tamanho) {
alcance *= 2;
comparacoes++;
}
return comparacoes + 1;
}
int main(void) {
int numeros[TAMANHO] = {45, 12, 78, 3, 91, 27, 56, 8, 63, 34};
int alvo = 63;
printf("====================================================\n");
printf(" ⚡ Motor de Busca Binaria e Benchmark de Ordenacao\n");
printf("====================================================\n");
printf("Vetor original (desordenado): ");
imprimir_vetor(numeros, TAMANHO);
ordenar_bubble_sort(numeros, TAMANHO);
printf("Vetor ordenado (Bubble Sort): ");
imprimir_vetor(numeros, TAMANHO);
int indice = busca_binaria(numeros, TAMANHO, alvo);
int comparacoes_reais = contar_comparacoes_busca_binaria(numeros, TAMANHO, alvo);
printf("\n----------------------------------------------------\n");
if (indice != -1) {
printf("Valor %d encontrado no indice %d.\n", alvo, indice);
} else {
printf("Valor %d nao encontrado no vetor.\n", alvo);
}
int pior_caso_linear = TAMANHO;
int pior_caso_binaria = comparacoes_pior_caso_binaria(TAMANHO);
printf("\n--- Benchmark de comparacoes (N = %d) ---\n", TAMANHO);
printf("Busca Linear -> pior caso teorico: %d comparacoes\n", pior_caso_linear);
printf("Busca Binaria -> pior caso teorico: %d comparacoes\n", pior_caso_binaria);
printf("Busca Binaria -> comparacoes reais nesta execucao: %d\n", comparacoes_reais);
printf("====================================================\n");
return EXIT_SUCCESS;
}
Por que isso importa: repare que busca_binaria e contar_comparacoes_busca_binaria implementam a mesma lógica, mas separadas — a segunda existe só para instrumentar (medir) a primeira sem poluir o código de produção com contadores. Esse padrão de “versão instrumentada para benchmark” é comum em engenharia de sistemas real.
Volte ao Miniprojeto 07 e reescreva o crivo de primos como um Crivo de Eratóstenes real: declare um array int eh_primo[101], inicialize todas as posições com 1 (exceto os índices 0 e 1), e para cada número p de 2 até 100, se eh_primo[p] ainda for 1, marque todos os seus múltiplos (2p, 3p, 4p, ...) como eh_primo[multiplo] = 0. No fim, percorra o array e imprima todos os índices ainda marcados como primos. Compare mentalmente: o Miniprojeto 07 testava cada número individualmente (força bruta); o crivo elimina múltiplos em lote, e é muito mais rápido para gerar todos os primos até N.
✅ Checkpoint: o crivo até 100 encontra 25 primos, de 2 a 97, os mesmos que a versão por divisão de tentativa do Miniprojeto 07 acharia.
📋 Projetos do curso de C | 📚 Teoria do Capítulo 10 | 🗂️ Hub de projetos