Commit inicial - add do repo privado para o repo NT style: changes header's logo and colors style: changes home page first session layout feat: creates about us home page section chore: creates home page section for whom chore: creates student materails home page section chore: creates teachers materials home page section chore: creates teacher materials home page section style: changes primary color style: changes color at activities page style: changes about page color style: changes name to Decoda fix: changes route to about page at footer fix: changes background color style: changes game page header colors style: changes footer colors chore: adds home page sections title style: changes main font family to Lato style: adds title font fix: changes sizes to be more responsive for mobile ajuste no build vercel atualiza regras envio homol Adiciona instrucoes de uso add JupyterLite fix solucao turtle Add Mole Mash e Modal de Falhas Add Progress Bar na pagina de Atividades fix game name chore: atualiza lockfile removendo vercel analytics inclusão de efeito ao mudar de fase add mecanismo de solução de fases em debug vite config test add BaseGame e refator do MoleMash refatoração turtle refatoração automato refatoração automato add tag bug 1 e 2 automato mostrar apenas games em homologação na pagina de atividades aumentar timeout das fases finais do Turtle fix bug scroll add video refactor semaforo arrumar ordem das cores add build docs update vercel update vercel update vercel update vercel update vercel add vercel jupyter add vercel jupyter fix deploy Vercel fix deploy Vercel fix deploy Vercel add cripto add cripto refatoração fix tour Mole Mash . remover arquivos de controle chore: adds development tag for activity card remover arquivos de status indevidamente versionados atualizar cores nas atividades add Quebra Cabeças add Quebra Cabeças add iniciativas add Iniciativas alteração de fotos pesadas fix menu mobile fix menu mobile fix menu mobile add Aspirador update icons update identidade visual documentação update jupyter add kernel python local add kernel python local add kernel python local feat: add health check feat: add primeiros passos add letramento mover letramento de lugar update path games update path games fix: ajuste clique rapido no botão executar remover dead code fix: refactor: extract shared utilities for storage, phase unlock and mobile detection stabilize context references and fix stale closure extrair GameProgressContext do GameStateContext (SRP) refactor(game): extrair usePhaser e useGameModals de GameBase + corrigir bugs descobertos refactor(game): remove todos os aliases PT/EN duplicados Remover aliases PT/EN da camada de modais refactor + tests security: add CodeSanitizer and integrate into GameInterpreter - CodeSanitizer.js: 4 built-in rules (max_length, infinite_while, infinite_for, excessive_nesting) with pluggable extra rules - GameInterpreter.executeCode: calls sanitizeCode() before js-interpreter, differentiates CodeSanitizationError (warn) from other errors (error) - 21 unit tests for CodeSanitizer (100% coverage) - 4 integration tests in GameInterpreter for sanitization paths add CodeSanitizer fix: fase 10 aspirador fix: bug semaforo teste feat: add version Ajusta a landing page para ficar mais próxima ao protótipo ajusta raio da borda do botão de Acesse nosso Laboratório pequenos ajustes de layout na página de iniciativas atualiza tabela de jogos educativos com os jogos disponíveis atualmente ajustados pequenos detalhes e informações do jogos na seção de guias pedagógicos troca nome playground para laboratório e adiciona imagens do lab adiciona documentação de conceitos básicos de programação ajustado pequenos erros de digitação adiciona tooltip com conceitos escondidos em hover na tag +N de conceitos update docs dev desativar tour setup matriz MoleMash setup matriz MoleMash fix: link update version update docs update docs mudou o layout de quem somos mudei as imgs dos icons e baixei o botao centraliza titulo com imagem e ajusta sessão com gradiente vermelho-rosa adiciona responsividade para a pagina quem somos ajusta botão de conheça nossa história ajustes ajustes na home + add. teclado update version security security feat: add tapume para telas pequenas v1.1.0 feat: decoda offline feat: doc offline offline fix: ajustes para release fix: navbar; config ordenação; versão fix: rotas docs e jupyter para pwa delete private files Co-authored-by: Indra Araujo <indra.araujo.santos@gmail.com> Co-authored-by: solange dos santos <sollangelive71@gmail.com>
18 KiB
title, sidebar_position
| title | sidebar_position |
|---|---|
| Ordenação | 9 |
Ordenação
Ordenação apresenta um dos problemas mais estudados da computação — colocar uma lista em ordem crescente — e o explora por múltiplos ângulos. O estudante implementa, fase a fase, cinco estratégias diferentes para o mesmo problema e percebe que cada uma tem uma lógica distinta, um custo diferente e situações em que funciona melhor ou pior.
Ao contrário de atividades que permitem soluções abertas, aqui cada fase exige um algoritmo específico. A validação verifica não só se a lista ficou ordenada, mas se o padrão de execução corresponde ao algoritmo pedido. Isso leva o estudante a entender o que torna cada algoritmo diferente — não apenas a chegar no resultado.
O que esta atividade ensina sobre programação
Ordenação é um contexto muito fértil para trabalhar estruturas de repetição aninhadas, variáveis de controle e operações sobre listas. Mas o que a distingue das demais atividades é que ela introduz uma ideia central da computação: diferentes algoritmos podem resolver o mesmo problema, com estratégias e custos radicalmente distintos.
Nas fases iniciais, o estudante pratica comparação e troca de dois ou três elementos com condicionais simples — consolidando o básico. A progressão avança para os algoritmos clássicos: Bubble Sort, Selection Sort, Insertion Sort, Shell Sort e Counting Sort. Cada um representa uma abordagem diferente, dos mais intuitivos aos que fogem completamente do paradigma de comparação direta.
A atividade também é uma porta de entrada concreta para análise de algoritmos. Sem precisar de formalismo matemático, o estudante pode observar quantas operações cada estratégia realiza, comparar resultados e começar a pensar em eficiência — uma competência que vai além da programação e se aplica a qualquer tipo de problema que exige raciocínio sobre custo e escala.
Os algoritmos
Cada algoritmo desta atividade representa uma estratégia diferente para o mesmo problema. Os diagramas abaixo mostram o fluxo lógico de cada um.
Bubble Sort
O Bubble Sort percorre a lista repetidamente, comparando pares de elementos adjacentes e trocando os que estão fora de ordem. A cada passada completa, o maior elemento ainda desordenado chega à sua posição final. O processo se repete até que nenhuma troca seja necessária.
flowchart TD
A[Início] --> B[Nova passada pela lista]
B --> C[i = 0]
C --> D{elemento atual maior que o próximo?}
D -->|Sim| E[Trocar os dois]
D -->|Não| F[i = i + 1]
E --> F
F --> G{Fim da passada?}
G -->|Não| D
G -->|Sim| H{Alguma troca ocorreu?}
H -->|Sim| B
H -->|Não| I[Lista ordenada]
A versão com otimização acrescenta uma variável de controle que detecta quando nenhuma troca ocorreu na passada — o que significa que a lista já está ordenada — encerrando o algoritmo antes das passadas restantes.
Quando é vantajoso
O Bubble Sort brilha quando a lista já está quase ordenada: com a otimização de parada antecipada, ele pode terminar em uma única passada, com custo proporcional ao tamanho da lista. É também o algoritmo mais fácil de implementar e depurar, o que o torna o ponto de partida natural para quem está aprendendo ordenação.
Quando não é a melhor escolha
Em listas grandes e desordenadas, o Bubble Sort realiza um número quadrático de comparações e trocas — o que o torna impraticável para volumes acima de alguns milhares de elementos. Em performance real, costuma ser o mais lento entre os algoritmos O(n²) porque acumula muitas trocas por passada.
Onde é usado
Por seu custo quadrático, o Bubble Sort raramente é escolhido em sistemas reais. Sua importância é quase inteiramente pedagógica: a lógica de "empurrar o maior elemento para o final a cada passada" é uma das mais intuitivas para entender o conceito de ordenação. Versões educacionais e ferramentas de visualização de algoritmos o utilizam amplamente por esse motivo.
Selection Sort
O Selection Sort divide a lista em duas partes: a porção já ordenada, que cresce da esquerda, e a porção desordenada. A cada passada, o algoritmo varre toda a parte desordenada para encontrar o menor elemento e o posiciona no início dela — com uma única troca por passada.
flowchart TD
A[i = 0] --> B[mínimo = i]
B --> C[j = i + 1]
C --> D{elemento j menor que elemento mínimo?}
D -->|Sim| E[mínimo = j]
D -->|Não| F[j = j + 1]
E --> F
F --> G{j chegou ao fim?}
G -->|Não| D
G -->|Sim| H[Trocar posições i e mínimo]
H --> I{i chegou ao penúltimo?}
I -->|Não| J[i = i + 1]
J --> B
I -->|Sim| K[Lista ordenada]
Uma característica do Selection Sort é que ele realiza exatamente n - 1 trocas, independente do estado inicial da lista — ao contrário do Bubble Sort, que pode realizar muitas mais.
Quando é vantajoso
O Selection Sort é vantajoso quando o custo de escrever na memória é significativamente mais alto do que o de ler — por exemplo, em memórias flash, onde cada escrita tem custo real de desgaste. Nesse contexto, fazer no máximo n - 1 trocas é uma vantagem concreta. Ele também é simples de implementar e tem comportamento previsível: o número de comparações é sempre o mesmo, independente da entrada.
Quando não é a melhor escolha
Assim como o Bubble Sort, o Selection Sort tem custo quadrático no número de comparações — mesmo que a lista já esteja ordenada, ele percorre toda a parte não ordenada a cada passada. Não existe versão com parada antecipada eficaz. Para listas grandes, algoritmos O(n log n) são muito mais eficientes.
Onde é usado
O Selection Sort aparece em contextos embarcados com memória muito limitada e escrita cara, como microcontroladores simples e dispositivos EEPROM. Em sistemas de uso geral, é substituído por algoritmos mais eficientes. Pedagogicamente, é valioso porque separa claramente a fase de busca do mínimo da fase de troca, tornando a lógica de duas etapas por passada muito explícita.
Insertion Sort
O Insertion Sort constrói a lista ordenada de forma incremental. Para cada elemento da parte desordenada, ele retrocede na parte já ordenada deslocando os elementos maiores uma posição para a direita, até encontrar o lugar certo para inserir o elemento atual.
flowchart TD
A[i = 1] --> B[guardar elemento da posição i]
B --> C[j = i - 1]
C --> D{j válido e elemento j maior que o guardado?}
D -->|Sim| E[Deslocar elemento j uma posição para a direita]
E --> F[j = j - 1]
F --> D
D -->|Não| G[Inserir o guardado na posição j + 1]
G --> H{i chegou ao fim?}
H -->|Não| I[i = i + 1]
I --> B
H -->|Sim| J[Lista ordenada]
O Insertion Sort é muito eficiente para listas quase ordenadas, pois precisa de poucos deslocamentos quando os elementos já estão próximos de sua posição final. É também a base do Shell Sort.
Quando é vantajoso
O Insertion Sort é uma das melhores escolhas para listas pequenas (tipicamente abaixo de 20 elementos) ou quase ordenadas. Nesses casos, ele supera algoritmos teoricamente mais eficientes como o Merge Sort, que carregam custo fixo maior de divisão e combinação. Para listas já ordenadas, seu custo é linear — O(n) — pois nenhum deslocamento é necessário.
Quando não é a melhor escolha
Em listas grandes e aleatórias, o custo quadrático domina. Cada novo elemento pode precisar ser deslocado até o início da lista, resultando em muitas operações de escrita. Para esses casos, algoritmos O(n log n) são necessários.
Onde é usado
O Insertion Sort está presente em implementações híbridas de algoritmos avançados. O Timsort — usado por padrão em Python e na JVM — aplica o Insertion Sort em blocos pequenos antes de combiná-los com Merge Sort. O IntroSort — base do std::sort do C++ — também recorre ao Insertion Sort quando a recursão chega a sublistas pequenas. É um algoritmo com papel real e ativo nos sistemas de produção mais difundidos.
Shell Sort
O Shell Sort é uma generalização do Insertion Sort. Em vez de inserir comparando apenas elementos vizinhos, ele começa comparando elementos separados por um intervalo inicial de metade do tamanho da lista. A cada rodada, esse intervalo é dividido ao meio. Quando o intervalo chega a 1, o comportamento é idêntico ao Insertion Sort — mas a lista já está bem próxima da ordem, então o trabalho restante é mínimo.
flowchart TD
A[intervalo = tamanho dividido por 2] --> B{intervalo maior ou igual a 1?}
B -->|Não| Z[Lista ordenada]
B -->|Sim| C[i = intervalo]
C --> D[guardar elemento da posição i]
D --> E[j = i - intervalo]
E --> F{j válido e elemento j maior que o guardado?}
F -->|Sim| G[Deslocar elemento j para a posição j + intervalo]
G --> H[j = j - intervalo]
H --> F
F -->|Não| I[Inserir o guardado na posição j + intervalo]
I --> J{i chegou ao fim?}
J -->|Não| K[i = i + 1]
K --> D
J -->|Sim| L[intervalo = intervalo dividido por 2]
L --> B
A intuição por trás do Shell Sort é que comparações de longa distância movem os elementos para perto de sua posição final muito mais rapidamente do que comparações vizinhas, reduzindo o trabalho das rodadas seguintes.
Quando é vantajoso
O Shell Sort é especialmente adequado para sistemas embarcados e ambientes sem suporte a recursão, onde algoritmos O(n log n) baseados em divisão (como Merge Sort e Quick Sort) são difíceis de implementar. Ele entrega desempenho subquadrático — na prática próximo de O(n log n) para sequências de intervalos bem escolhidas — com código iterativo simples e memória O(1).
Quando não é a melhor escolha
A complexidade do Shell Sort depende da sequência de intervalos escolhida, e a análise teórica ainda é um problema em aberto para algumas sequências. Em sistemas com suporte a recursão e memória suficiente, o Merge Sort ou o Timsort oferecem garantias mais sólidas e melhor desempenho em listas grandes.
Onde é usado
O Shell Sort é encontrado em firmwares, sistemas operacionais compactos e ambientes com pilha de chamadas limitada. O kernel do Linux e o uClibc utilizaram implementações de Shell Sort em contextos onde simplicidade e ausência de recursão eram mais importantes do que performance máxima. É também um ponto de passagem didático natural entre o Insertion Sort e os algoritmos baseados em divisão.
Counting Sort
O Counting Sort é fundamentalmente diferente dos anteriores: ele não compara elementos entre si. Em vez disso, conta quantas vezes cada valor aparece na lista e, a partir dessas contagens, reconstrói a lista já ordenada. Por isso, ele escapa do limite teórico inferior O(n log n) que vale para qualquer algoritmo baseado em comparação.
flowchart TD
A[Criar lista de contagem com zeros] --> B[Para cada elemento da lista]
B --> C[Incrementar a contagem do valor correspondente]
C --> D{Todos os elementos contados?}
D -->|Não| B
D -->|Sim| E[v = 0]
E --> F{v menor que tamanho da contagem?}
F -->|Não| G[Lista reconstruída]
F -->|Sim| H{contagem de v maior que zero?}
H -->|Não| I[v = v + 1]
I --> F
H -->|Sim| J[Adicionar v à próxima posição da lista]
J --> K[Decrementar contagem de v]
K --> H
Quando é vantajoso
O Counting Sort tem complexidade O(n + k), onde k é o valor máximo dos dados. Quando k é pequeno em relação a n, ele supera qualquer algoritmo de comparação: ordenar um milhão de notas escolares no intervalo 0–10 é muito mais rápido com Counting Sort do que com Bubble, Insertion ou até Merge Sort.
Ele também é a base do Radix Sort, que o aplica dígito a dígito para ordenar inteiros arbitrários em O(d · n), onde d é o número de dígitos.
Quando não é a melhor escolha
Quando k >> n — por exemplo, ordenar 10 números no intervalo [0, 1.000.000] — o algoritmo aloca um array de 1 milhão de posições desnecessariamente, com memória O(k) dominando o custo. Além disso, o Counting Sort não se aplica diretamente a dados com ponto flutuante, strings ou objetos complexos, nem a dados com distribuição desconhecida ou muito esparsa.
Comparação de complexidade
| Algoritmo | Tempo médio | Memória |
|---|---|---|
| Bubble / Insertion | O(n²) | O(1) |
| Merge / Heap | O(n log n) | O(n) / O(1) |
| Quick Sort | O(n log n) | O(log n) |
| Counting Sort | O(n + k) | O(k) |
Nas fases desta atividade, a lista tem 10 valores com máximo 55. O Counting Sort usa um array de 56 posições — mais memória do que o estritamente necessário para n=10, mas eficiente caso houvesse muitos elementos nessa faixa. Sua importância aqui é pedagógica: ilustrar que existem algoritmos que exploram propriedades dos dados para escapar do limite O(n log n), ao custo de restrições sobre o tipo e a faixa dos valores.
Onde é usado
O Counting Sort aparece como subroutine do Radix Sort, que o aplica dígito a dígito para ordenar inteiros de qualquer magnitude. Sistemas de contagem de votos, classificação de idades, notas ou qualquer dado inteiro com faixa pequena e conhecida são contextos naturais. Implementações de ordenação estável em sistemas de banco de dados também o utilizam quando os dados satisfazem as restrições de tipo e faixa. No ecossistema de algoritmos, ele representa a categoria dos algoritmos não comparativos — junto com o Radix Sort e o Bucket Sort — que quebram o limite teórico O(n log n) ao explorar a estrutura interna dos dados.
Mediação pedagógica
Uma abordagem eficaz é pedir que o estudante descreva o algoritmo em palavras antes de implementá-lo em blocos. "O que o Bubble Sort faz a cada passada?" ou "Como o Selection Sort escolhe o próximo elemento?" ajudam a separar a compreensão do algoritmo da habilidade de montá-lo. Se o estudante trava nos blocos, o problema está quase sempre na compreensão do algoritmo — não na ferramenta.
Outro recurso valioso é comparar soluções após a implementação. Dois algoritmos que produzem o mesmo resultado final podem ter realizado quantidades muito diferentes de operações. Perguntar "qual deles você acha que fez mais trabalho?" e em seguida observar o número de comparações e trocas — disponíveis nos dados de execução — torna a noção de eficiência concreta e baseada em evidência.
O Shell Sort e o Counting Sort merecem atenção especial na mediação. O Shell Sort exige que o estudante entenda por que comparar elementos distantes pode ser útil antes de comparar os vizinhos — uma ideia contraintuitiva que vale explorar antes de implementar. O Counting Sort, por sua vez, rompe com o modelo mental de "comparar e decidir" e pode gerar uma boa discussão sobre o que é realmente necessário para ordenar uma lista quando se conhece o intervalo dos dados.
Progressão das fases
| Fase | Nome | O que o estudante pratica |
|---|---|---|
| 1 | Ordenar 2 Números | usar condicional para comparar e trocar dois valores |
| 2 | Ordenar 3 Números | combinar repetição e condicionais para ordenar três elementos |
| 3 | Bubble Sort | comparar pares adjacentes em passadas repetidas |
| 4 | Bubble Sort com Otimização | adicionar controle de parada antecipada quando não há trocas |
| 5 | Selection Sort | encontrar o mínimo da parte desordenada e posicioná-lo com uma troca |
| 6 | Insertion Sort | inserir cada elemento na posição correta deslocando os maiores |
| 7 | Shell Sort | usar comparações com intervalo variável que diminui progressivamente até 1 |
| 8 | Counting Sort | contar ocorrências e reconstruir a lista sem comparar elementos |
Quando usar
Ordenação é indicada quando a turma já tem fluência com laços, variáveis e condicionais, e está pronta para um problema com múltiplas soluções corretas e eficiências distintas. É especialmente adequada em aulas que queiram discutir análise de algoritmos de forma introdutória, ou que queiram mostrar que a escolha da estratégia depende das características dos dados — não apenas da correção do resultado.
A atividade funciona bem como continuação natural após Cripto, já que ambas trabalham com transformação sistemática de informação regida por regras precisas. Se o objetivo incluir conceitos como memória auxiliar, troca entre espaço e tempo, ou a categoria de algoritmos não comparativos, o Counting Sort oferece um gancho concreto e didático para essa discussão.
Referências
- Algoritmos de ordenação: https://pt.wikipedia.org/wiki/Algoritmo_de_ordena%C3%A7%C3%A3o
- Bubble Sort: https://pt.wikipedia.org/wiki/Bubble_sort
- Selection Sort: https://pt.wikipedia.org/wiki/Selection_sort
- Insertion Sort: https://pt.wikipedia.org/wiki/Insertion_sort
- Shell Sort: https://pt.wikipedia.org/wiki/Shell_sort
- Counting Sort: https://pt.wikipedia.org/wiki/Counting_sort
- Complexidade computacional: https://pt.wikipedia.org/wiki/Complexidade_computacional