Trabalho Prático: Algoritmos de Ordenação em C¶
Formato: grupos de até 3 alunos · Linguagem: C (padrão C99 ou C11) · Duração sugerida: 4 semanas
Este trabalho é a avaliação prática da disciplina e tem duas entregas indissociáveis: o código (repositório GitHub) e um vídeo de defesa obrigatório, no qual o grupo demonstra e explica o que implementou. O vídeo não é um extra — é a etapa final do trabalho e substitui a avaliação escrita da Terceira Unidade.
Objetivos de Aprendizagem¶
- Implementar 3 algoritmos básicos e 3 algoritmos avançados de ordenação em C.
- Vivenciar o controle de versão com Git em equipe, com fluxo flexível e focado no histórico.
- Aplicar noções básicas de qualidade e medição: testes, cobertura (
gcov) e profiling de desempenho (gprof). - Produzir documentação técnica e análise empírica dos resultados.
- Desenvolver transparência acadêmica no uso de IA, validando e explicando todo o código entregue.
- Defender oralmente as escolhas de implementação e os resultados obtidos.
Organização do Grupo¶
Cada grupo define sua própria divisão de tarefas. Sugestão inicial (opcional):
- Membro 1: algoritmos básicos + testes iniciais
- Membro 2: algoritmos avançados + benchmarks
- Membro 3: qualidade (
gcov,gprof,cppcheck),Makefilee documentação
Regra única: todos devem conseguir compilar, executar e explicar qualquer parte do código — isso será cobrado diretamente no vídeo. O histórico Git deve refletir contribuição ativa de pelo menos 2 integrantes.
Parte 1 — Implementação¶
Algoritmos Obrigatórios¶
| Categoria | Algoritmos | Assinatura Padrão |
|---|---|---|
| Básicos | Bubble Sort, Selection Sort, Insertion Sort | void algoritmoSort(int v[], int n); |
| Avançados | Merge Sort, Quick Sort, Heap Sort | void algoritmoSort(int v[], int n); |
Cada algoritmo deve estar em arquivo .c separado. O main.c pode conter chamadas, menu ou execução direta dos testes.
Fluxo Git/GitHub¶
Não há exigência de branch protection, revisão obrigatória ou bloqueio de push direto na main. O foco é criar o hábito de versionar incrementalmente.
Esperado no histórico:
- Commits frequentes: mínimo 1 a cada 2-3 dias de trabalho.
- Mensagens descritivas, seguindo o padrão
tipo: descrição(ex.:feat: adiciona heap sort,fix: corrige índice no partition do quicksort,docs: atualiza benchmark e uso de IA). Evite mensagens comoupdate,fix,salva tudo. - Participação visível:
git logdeve mostrar commits de pelo menos 2 emails/nomes diferentes. - Branches & PRs: opcionais. Podem trabalhar direto na
mainou criar branches por funcionalidade. Se usarem PRs, basta uma descrição breve.
Tip
Rode git pull antes de começar e git push depois de testar uma nova funcionalidade. Isso evita conflitos e gera histórico natural.
Compilação¶
- Compilação via
make(modelo no apêndice). - Zero erros de compilação. Warnings críticos devem ser corrigidos.
Testes¶
- Arquivo
tests/test_basic.ccom no mínimo 2 casos por algoritmo (ex.: vetor aleatório, já ordenado, invertido). - Cada teste deve imprimir
PASSOUouFALHOU. - Comando:
make test.
Cobertura de Código (gcov)¶
O gcov mede quais linhas do programa foram de fato executadas pelos testes.
-
Compile com suporte a cobertura:
As flags equivalentes
-fprofile-arcs -ftest-coveragefazem o GCC gerar os arquivos (.gcno) necessários para ogcov. -
Execute o programa ou a suíte de testes (
./mainoumake test). Isso gera um arquivo.gcdacom as estatísticas de execução. -
Gere o relatório:
O resultado é um arquivo
main.c.gcove um resumo no terminal, por exemplo: -
Interprete o resultado. No arquivo
.gcov, cada linha é prefixada pelo número de vezes que foi executada, ou por#####se nunca foi executada: -
Cobertura de branches (opcional). Para ver quais desvios (
if,while, ...) foram de fato tomados:
Para um relatório HTML mais legível, use gcovr ou lcov:
Profiling de Desempenho (gprof)¶
Enquanto o gcov responde "quais linhas foram executadas?", o gprof responde "onde o programa gastou mais tempo?".
-
Compile com suporte a profiling (flag
-pg, sem otimização): -
Execute o programa (
./bubble). Isso gera o arquivogmon.outcom os dados coletados. -
Gere o relatório:
A saída inclui um flat profile (tempo gasto por função):
Flat profile: Each sample counts as 0.01 seconds. % cumulative self time seconds seconds calls ms/call ms/call name 85.0 0.17 0.17 1 170.00 170.00 bubbleSort 10.0 0.19 0.02 1 20.00 20.00 imprimirVetor 5.0 0.20 0.01 1 10.00 10.00 maine um call graph, mostrando quem chamou quem, quantas vezes e quanto tempo cada chamada consumiu — útil para identificar gargalos que não aparecem no flat profile.
Warning
Não faça profiling com -O2. O otimizador distorce as medições — sempre use -O0 (o alvo make profile do Makefile do apêndice já cuida disso).
Outras ferramentas relacionadas, caso queiram ir além: valgrind --tool=massif (uso de memória), valgrind --tool=callgrind (perfil detalhado de chamadas) e perf (profiling de sistema no Linux).
Política de Uso de IA & Transparência¶
Permitido e incentivado: gerar trechos para estudo, pedir explicação de erros, revisar formatação, sugerir nomes de variáveis, usar como tutor.
Não permitido: entregar código completo sem entender, testar ou adaptar; ocultar prompts ou ferramentas utilizadas.
Crie docs/uso-ia.md seguindo este modelo:
# Uso de Ferramentas de IA no Projeto
## Ferramentas Utilizadas
- [ ] ChatGPT / GPT-4o
- [ ] GitHub Copilot
- [ ] Claude / Gemini
- [ ] Outra: _______________
## Como Usamos (exemplos reais)
| Prompt / Solicitação | O que a IA gerou | O que adaptamos/validamos |
|----------------------|------------------|---------------------------|
| "Explique como o heapify restaura o max-heap" | Texto + pseudocódigo | Reescrevemos em C, ajustamos índices 2i+1 e adicionamos testes |
| "Corrija warning unused variable em merge.c" | Sugeriu remover var | Mantivemos, renomeamos e usamos no laço |
## Validação & Domínio
- [ ] Compilamos e rodamos todo código gerado ou sugerido
- [ ] Todos conseguem explicar o funcionamento de cada algoritmo em 2 minutos
- [ ] Não submetemos blocos inteiros sem revisão linha a linha
## Reflexão Final (3-5 linhas)
(Descreva onde a IA ajudou, onde atrapalhou, e o que o grupo aprendeu ao questionar as respostas.)
Avaliação
O uso de IA não penaliza. Falta de transparência, código não testado ou grupo incapaz de explicar a entrega penaliza.
Estrutura Obrigatória do Repositório¶
ordenacao-trio/
├── README.md # Instruções de build, membros, links
├── Makefile # Modelo fornecido
├── src/
│ ├── basicos/ # bubble.c, selection.c, insertion.c
│ ├── avancados/ # merge.c, quick.c, heap.c
│ └── main.c # Ponto de entrada
├── tests/
│ └── test_basic.c # Testes manuais
├── docs/
│ ├── cobertura.md # Relatório gcov + análise
│ ├── perfil_bruto.txt # Saída do gprof (gerada automaticamente)
│ ├── perfil.md # Interpretação do profiling
│ └── uso-ia.md # Transparência de prompts e validação
└── .gitignore
Cronograma Sugerido¶
| Semana | Foco | Meta Git |
|---|---|---|
| 1 | Setup, Makefile, 2 básicos, 1 teste cada |
Commits iniciais + estrutura |
| 2 | Completar básicos, 2 avançados, testes rodando | Histórico crescente (≥ 5 commits) |
| 3 | Completar avançados, gcov, gprof, cppcheck |
Commits de refino + docs/ |
| 4 | Ajustes finais, gravação do vídeo, tag v1.0 |
Entrega + link no SIGAA |
Parte 2 — Defesa em Vídeo (obrigatória)¶
O vídeo é a defesa oral do trabalho: demonstra que o grupo domina o código desenvolvido e as ferramentas utilizadas, e substitui a avaliação escrita da Terceira Unidade (4,0 pontos).
- Formato: gravação de 8 a 15 minutos, publicada no YouTube (público ou não listado).
- Envio: o link do vídeo é enviado no SIGAA junto com a entrega do repositório.
- Não serão aceitas apresentações compostas apenas de slides — é obrigatório alternar para a tela do terminal e do editor, mostrando código e execução real.
- Os grupos devem ser exatamente os mesmos do trabalho prático, e todos os integrantes devem falar e demonstrar autoria do código.
Estrutura Obrigatória do Vídeo¶
- Apresentação da equipe: integrantes, turma e objetivos gerais.
- Implementação dos algoritmos: organização do código-fonte (arquivos e estrutura) e explicação das partes relevantes.
- Demonstração da execução: compilar e executar o programa ao vivo, mostrando entrada de dados, saída dos testes e coleta das métricas.
- Análise experimental: discutir a tabela de tempos de execução, comparações e trocas, confrontando o desempenho medido com a teoria de complexidade.
- Uso de ferramentas: demonstrar o funcionamento do
gcov(cobertura obtida),gprof(funções mais pesadas) ecppcheck(correções feitas). - Conclusões: qual algoritmo performou melhor, se as medições batem com a teoria estudada e quais dificuldades a equipe encontrou.
Avaliação¶
Rubrica do Código (100 pts)¶
| Critério | O que será observado | Peso |
|---|---|---|
| Funcionalidade | 6 algoritmos compilam, executam e ordenam corretamente | 25 |
| Histórico Git | Commits regulares, mensagens claras, participação do grupo, evolução visível | 20 |
| Qualidade & Testes | Testes passam, gcov ≥ 70% nas funções, cppcheck limpo de erros críticos |
20 |
| Documentação & Análise | docs/cobertura.md, docs/perfil.md, README funcional |
20 |
| Colaboração & IA | Divisão equilibrada, docs/uso-ia.md preenchido, código explicável |
15 |
Warning
Repositórios com 1-2 commits no dia da entrega, mensagens vazias ou código que o grupo não consegue modificar serão penalizados na categoria Git/Colaboração.
Rubrica do Vídeo (4,0 pts — substitui a avaliação escrita da Unidade 3)¶
| Critério | O que será observado | Pontos |
|---|---|---|
| Organização e Clareza | Apresentação didática, áudio nítido, divisão do tempo e boa estrutura | 1.0 |
| Demonstração do Código | Explicação concisa da implementação e compilação/execução correta | 1.0 |
| Análise de Resultados | Discussão fundamentada nas medições empíricas comparando os algoritmos | 1.0 |
| Domínio e Participação | Todos os integrantes falam e demonstram autoria do código | 1.0 |
Entrega do Projeto¶
- Repositório GitHub atualizado (público, ou privado com acesso liberado ao professor).
-
Tag de versão da entrega final:
-
Envio via SIGAA, em um único comentário por grupo, contendo:
- nomes completos dos integrantes;
- link do repositório GitHub;
- link do vídeo de apresentação no YouTube.
Apêndice: Makefile Base¶
Copie este arquivo para a raiz do repositório. Ele já inclui alvos para compilação, testes, gcov e gprof.
CC = gcc
CFLAGS = -Wall -Wextra -std=c11 -O2
GCOV_FLAGS = -fprofile-arcs -ftest-coverage -g
PROFILE_FLAGS = -pg -g -O0
SRCS = src/main.c src/basicos/bubble.c src/basicos/selection.c src/basicos/insertion.c \\
src/avancados/merge.c src/avancados/quick.c src/avancados/heap.c
TEST_SRCS = tests/test_basic.c $(filter-out src/main.c,$(SRCS))
OBJS = $(SRCS:.c=.o)
TEST_OBJS = $(TEST_SRCS:.c=.o)
TARGET = sort_main
TEST_TARGET = test_basic
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
$(TEST_TARGET): $(TEST_OBJS)
$(CC) $(CFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
test: $(TEST_TARGET)
./$(TEST_TARGET)
coverage: CFLAGS += $(GCOV_FLAGS)
coverage: clean test
@echo "Dados de cobertura gerados. Rode: gcov src/basicos/*.c src/avancados/*.c"
profile: clean
$(CC) $(PROFILE_FLAGS) $(CFLAGS) -o sort_profile $(SRCS) tests/test_basic.c
./sort_profile
gprof sort_profile gmon.out > docs/perfil_bruto.txt
@echo "Profiling gerado em docs/perfil_bruto.txt"
@echo "Abra o arquivo e analise a seção 'Flat Profile'"
clean:
rm -f $(TARGET) $(TEST_TARGET) sort_profile $(OBJS) $(TEST_OBJS) *.gcda *.gcno *.gcov gmon.out
.PHONY: all test coverage profile clean
Dicas Rápidas¶
| Ferramenta | Dica |
|---|---|
gcov |
Se a cobertura ficar abaixo de 70%, adicione testes com n=0, n=1, vetores com duplicatas e invertidos. |
gprof |
Não rode com -O2 — o otimizador distorce medições. Use make profile (já aplica -O0). |
git |
Uma mensagem como fix: ajusta condição de parada no quicksort vale mais que 10 commits update. |
| IA | Peça explicação, não código pronto. Valide linha a linha — a IA é copiloto, não piloto. |
| Entrega | Teste make clean && make all && make test && make coverage && make profile antes de dar push. |