Algoritmos e Lógica de Programação: O Mapa que Todo Desenvolvedor Precisa
Aprenda a resolver problemas no papel antes de codificar. Entenda sequência, seleção, repetição, algoritmos de ordenação e complexidade Big O.

Você não travou porque algoritmos são difíceis. Travou porque ninguém te mostrou o problema antes de te entregar a solução. Esse artigo corrige isso — do conceito mais simples até análise de complexidade.
Essa sensação tem nome — e tem solução. Ela acontece quando você tenta escrever código antes de pensar no algoritmo. É como tentar construir uma casa sem planta: você até levanta algumas paredes, mas logo percebe que o banheiro ficou no lugar errado.
Este artigo vai te mostrar o mapa que todo desenvolvedor precisa dominar antes de digitar a primeira linha de código.
O que é um Algoritmo, de Verdade?
Um algoritmo é simplesmente uma sequência finita e ordenada de passos para resolver um problema. Sem ambiguidade. Sem passos que dependem de adivinhação. Cada instrução precisa ser clara o suficiente para que uma máquina — que não pensa, apenas executa — consiga seguir.
Pense na receita de bolo da sua avó. Ela tem ingredientes (dados de entrada), uma ordem de preparo (passos executáveis) e um resultado esperado (saída). Se você pular um passo ou trocar a ordem, o bolo não sai certo. Com algoritmos, a lógica é exatamente a mesma.
As Três Estruturas que Governam Tudo
Toda a lógica de programação — independente da linguagem — se apoia em apenas três estruturas de controle. Sim, apenas três.

1. Sequência
A mais simples. Os passos são executados um após o outro, na ordem em que aparecem.
int x = 10;int y = 20;int soma = x + y;printf("Resultado: %d\n", soma);Nada de surpresa. O computador lê linha por linha, de cima para baixo.
2. Seleção (Decisão)
Aqui o programa ganha inteligência. Dependendo de uma condição, ele escolhe um caminho ou outro.
if (temperatura > 38) { printf("Febre detectada. Consulte um médico.\n");} else { printf("Temperatura normal.\n");}Existem três formas principais de seleção:
Simples: um ou dois caminhos alternativos (
if/else)Encadeada: escolha entre vários caminhos (
if/else if/else)Múltipla: comparar uma variável com vários valores fixos (
switch/case)
O switch/case é perfeito quando você tem muitas opções bem definidas — como os dias da semana ou as opções de um menu.
3. Repetição (Laços)
O coração da automação. Executar o mesmo bloco de código várias vezes sem precisar reescrevê-lo.
Repetição contada — quando você sabe exatamente quantas vezes vai repetir:
for (int i = 1; i <= 10; i++) { printf("%d\n", i);}Repetição com pré-condição — quando você testa a condição antes de entrar no laço:
while (saldo > 0) { saldo -= parcela;}Repetição com pós-condição — quando o bloco precisa executar pelo menos uma vez:
do { printf("Digite um número positivo: "); scanf("%d", &numero);} while (numero <= 0);Tipos de Dados: A Matéria-Prima do Programa
Antes de processar qualquer informação, o computador precisa saber com que tipo de dado está lidando. Em C, os tipos básicos são:
Tipo | O que armazena | Exemplo |
|---|---|---|
int | Números inteiros | 42, -7, 0 |
float | Números com casas decimais | 3.14, -0.5 |
char | Um único caractere | 'A', 'z' |
char[] | Cadeia de caracteres (texto) | "Olá, mundo" |
Esses dados vivem como variáveis (valores que mudam durante a execução) ou constantes (valores que nunca mudam). Usar constantes para valores fixos — como PI = 3.14159 — torna o código mais legível e seguro.
Funções: O Segredo do Código Limpo
Se você se pegar repetindo o mesmo bloco de código em lugares diferentes, é sinal de que aquele trecho merece virar uma função.
Uma função é um bloco de código com um objetivo específico. Ela recebe dados (parâmetros), processa e devolve um resultado.
float calcularMedia(float nota1, float nota2, float nota3) { return (nota1 + nota2 + nota3) / 3;}Existem dois tipos fundamentais:
void: a função executa uma ação e não devolve nada (como imprimir na tela)
Tipada (int, float...): a função faz um cálculo e devolve um resultado
Boas Práticas que Fazem Diferença
Dominar a sintaxe é a parte fácil. O que separa um código amador de um código profissional são os hábitos.
Planeje antes de codificar. Antes de abrir o editor, defina: quais dados entram? Quais saem? Qual a sequência de passos? Um rascunho em papel vale mais do que uma hora de tentativa e erro.
Comente o que não é óbvio. O compilador ignora comentários, mas seus colegas (e você mesmo, daqui a seis meses) não. Documente a intenção do código, não apenas o que ele faz.
// Calcula o índice de massa corporal conforme tabela da OMSfloat imc = peso / (altura * altura);Escreva código portável. Evite funções específicas de um sistema operacional quando existir uma alternativa no padrão ISO do C. Código portável roda em Windows, Linux e Unix sem modificações.
Use nomes significativos. temperatura, contador, nomeUsuario são infinitamente melhores que t, c, n. Clareza não é frescura — é respeito pelo próximo que vai ler seu código.
Algoritmos Clássicos que Todo Programador Deve Conhecer
Teoria sem prática é decoração. Veja como os conceitos acima se materializam em algoritmos reais — os mesmos usados em bancos de dados, sistemas de busca e aplicações do dia a dia.
Busca Linear vs. Busca Binária: a diferença que muda tudo
Imagine que você precisa encontrar o número 23 em uma lista de mil números.
Busca Linear — verifica um por um, do início ao fim:
def busca_linear(lista, alvo): for i in range(len(lista)): if lista[i] == alvo: return i # retorna o índice onde encontrou return -1 # não encontradonumeros = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]print(busca_linear(numeros, 23)) # saída: 5Funciona. Mas no pior caso, percorre todos os elementos. Em uma lista de um milhão? Um milhão de comparações.
Busca Binária — divide o problema ao meio a cada passo. Requer lista ordenada:
def busca_binaria(lista, alvo): inicio = 0 fim = len(lista) - 1 while inicio <= fim: meio = inicio + (fim - inicio) // 2 if lista[meio] == alvo: return meio # encontrou! elif lista[meio] < alvo: inicio = meio + 1 # descarta a metade esquerda else: fim = meio - 1 # descarta a metade direita return -1 # não encontradonumeros = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]print(busca_binaria(numeros, 23)) # saída: 5Algoritmo | Pior caso (1 milhão de itens) | Requer ordenação? |
|---|---|---|
Busca Linear | 1.000.000 comparações | Não |
Busca Binária | ~20 comparações | Sim |

Algoritmos de Ordenação: colocando a casa em ordem
Para usar a busca binária, você precisa de dados ordenados. E para ordenar dados, você precisa de um algoritmo de ordenação.
Bubble Sort — o mais simples para entender. Funciona como bolhas subindo à superfície: a cada passagem, o maior elemento flutua para o fim:
def bubble_sort(lista): n = len(lista) for i in range(n): for j in range(0, n - i - 1): # se o elemento atual é maior que o próximo, troca if lista[j] > lista[j + 1]: lista[j], lista[j + 1] = lista[j + 1], lista[j] return listanumeros = [64, 34, 25, 12, 22, 11, 90]print(bubble_sort(numeros)) # [11, 12, 22, 25, 34, 64, 90]O mesmo algoritmo em C:
void bubble_sort(int arr[], int n) { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } }}Recursão: quando a função chama a si mesma
Um conceito que assusta iniciantes mas é elegante quando você entende: uma função que resolve um problema chamando a si mesma com uma versão menor do mesmo problema.
def fatorial(n): # caso base: para a recursão if n == 0 or n == 1: return 1 # chamada recursiva com problema menor return n * fatorial(n - 1)print(fatorial(5)) # 5 × 4 × 3 × 2 × 1 = 120Toda função recursiva tem dois componentes obrigatórios:
Caso base: a condição de parada (sem ela, recursão infinita)
Chamada recursiva: o problema reduzido a uma versão menor de si mesmo
Recursão é a base de algoritmos poderosos como Merge Sort, busca em árvores e travessia de grafos.
Complexidade de Algoritmos: o custo do que você escreve
Todo algoritmo tem um custo. A notação Big O descreve como esse custo cresce conforme o tamanho da entrada aumenta.
Notação | Nome | Exemplo |
|---|---|---|
O(1) | Constante | Acessar elemento de array por índice |
O(log n) | Logarítmica | Busca Binária |
O(n) | Linear | Busca Linear |
O(n log n) | Linearítmica | Merge Sort, Quick Sort |
O(n²) | Quadrática | Bubble Sort, Selection Sort |

O Erro Mais Comum de Quem Está Começando
A maioria dos iniciantes tenta aprender programação aprendendo linguagem.
Decoram a sintaxe do if, do for, do while — mas quando chegam em um problema real, travam. Porque o problema nunca é a sintaxe. O problema é a lógica.
A linguagem é apenas a notação. O algoritmo é o pensamento.
Esse hábito — aparentemente simples — é o que diferencia um programador que avança de um que fica preso eternamente nos tutoriais.
Conclusão
Algoritmos e lógica de programação não são matéria de faculdade. São a base de tudo que você vai construir como desenvolvedor.
Sequência, seleção e repetição. Tipos de dados. Funções bem nomeadas. Busca binária. Complexidade Big O. Planejamento antes do código.
Esses conceitos não saem de moda. Não importa se a linguagem do momento é C, Python, JavaScript ou qualquer outra que surgir nos próximos anos — a lógica por trás de todas elas é a mesma.


