Um algoritmo é uma receita pra resolver um problema: uma sequência finita de passos que, dado um input, produz um output. Existe muito antes do computador — e a forma como a gente escreve algoritmos hoje é resultado de uma evolução de mais de 2 mil anos. Esta página percorre essa linha do tempo em 6 paradas, do papiro até o Clean Code.
A ideia de "passo a passo pra resolver um problema" não nasceu com a informática. Ela é matemática pura, e tem nomes bem antigos.
| Quando | Quem | O quê |
|---|---|---|
| ~300 a.C. | Euclides | Algoritmo de Euclides — calcula MDC de dois números. Considerado o primeiro algoritmo formal documentado. |
| séc. IX | Al-Khwarizmi | Matemático persa. O nome "algoritmo" vem da latinização do nome dele (Algoritmi). Também deu origem à palavra "álgebra". |
| 1843 | Ada Lovelace | Escreveu o primeiro algoritmo destinado a uma máquina (a Máquina Analítica de Babbage, que nunca chegou a ser construída). É considerada a primeira programadora. |
| 1936 | Alan Turing | Define formalmente o que é "computável" com a Máquina de Turing — modelo teórico que fundamenta a ciência da computação. |
Ou seja: quando o primeiro computador foi ligado, já tinha 2 mil anos de teoria de algoritmos esperando.
Os primeiros computadores eletrônicos (anos 40) eram programados diretamente em binário — sequências de 0 e 1 que o processador entende como instruções.
Cada CPU tem um conjunto de instruções próprio. Uma instrução pra somar dois números pode ser algo como 10110000 01100001. Programar assim é tedioso e propenso a erro — qualquer bit trocado quebra o programa.
Veio em seguida como uma camada fina por cima do binário. Em vez de 10110000, você escreve MOV AL, 61h. Cada instrução Assembly corresponde a uma instrução de máquina (relação 1:1), mas com nomes legíveis (mnemônicos).
; soma dois números em Assembly x86
MOV AX, 5 ; coloca 5 no registrador AX
ADD AX, 3 ; soma 3 ao AX
; AX agora vale 8
Ainda é colado no hardware: você precisa saber quais registradores existem, como a CPU lê memória, etc. Não tem if, não tem for, não tem função — só JUMP (pular pra outro lugar do código).
Anos 50 e 60. O custo de programar em Assembly era altíssimo — cada projeto reinventava a roda. Surgem as linguagens de alto nível: você escreve algo próximo da matemática e um compilador traduz pra Assembly.
| Ano | Linguagem | Foco |
|---|---|---|
| 1957 | FORTRAN | Cálculo científico. Primeira linguagem de alto nível com adoção real. |
| 1958 | LISP | Inteligência artificial. Inventou o paradigma funcional. |
| 1958 | ALGOL | Linguagem acadêmica. Inventou os blocos de código, o if/then/else, o for, o while e o conceito de função recursiva. |
| 1959 | COBOL | Aplicações comerciais. Ainda roda em bancos hoje. |
| 1972 | C | Síntese: rápido como Assembly, estruturado como ALGOL. Vira a base do mundo Unix e fundação de quase tudo que veio depois. |
Quando alguém pergunta "onde foram criados os for, while, if, e funções?" — a resposta é ALGOL 58/60. Antes dele, o controle de fluxo era feito com GOTO (pular pra um número de linha). ALGOL inventou:
BEGIN/END (depois viraria { } no C)if-then-else, for, whileEdsger Dijkstra publica "Go To Considered Harmful" — um manifesto contra o uso de GOTO. Defende que todo algoritmo pode (e deve) ser escrito apenas com sequência, seleção (if) e repetição (loops). Esse paradigma ficou conhecido como programação estruturada e dominou os anos 70/80.
O C (Dennis Ritchie, 1972) consolidou tudo isso numa linguagem prática e portátil. Sintaxe enxuta, performance perto do Assembly, e a possibilidade de escrever sistemas operacionais inteiros (Unix). Java, JavaScript, Python, C# — todas herdam sintaxe do C.
// um algoritmo estruturado em C — soma de 1 a N
int somatorio(int n) {
int total = 0;
for (int i = 1; i <= n; i++) {
total += i;
}
return total;
}
Em 1968, Donald Knuth começa a publicar The Art of Computer Programming — uma série de livros que formaliza algoritmos como disciplina científica. A pergunta deixa de ser "esse código funciona?" e passa a ser "esse código é eficiente?".
Diferentes formas de organizar dados na memória, cada uma boa pra um tipo de operação:
| Estrutura | Pra que serve | Exemplo |
|---|---|---|
| Array / Lista | Acesso por índice | Lista de produtos no carrinho |
| Pilha (Stack) | Último a entrar, primeiro a sair (LIFO) | Botão "voltar" do navegador |
| Fila (Queue) | Primeiro a entrar, primeiro a sair (FIFO) | Fila de impressão |
| Hash / Dicionário | Busca por chave em tempo constante | Cache de sessão por user_id |
| Árvore | Hierarquia + busca rápida | Sistema de arquivos, índices de banco |
| Grafo | Relações entre entidades | Rede social, mapa de ruas (GPS) |
Notação que descreve como o tempo cresce conforme o input cresce, ignorando constantes. É o vocabulário universal pra dizer se um algoritmo escala.
| Big O | Como cresce | Exemplo |
|---|---|---|
O(1) | Constante | Acesso a item de array por índice |
O(log n) | Logarítmico — muito bom | Busca binária, busca em árvore balanceada |
O(n) | Linear | Percorrer uma lista |
O(n log n) | Bom pra ordenação | MergeSort, QuickSort |
O(n²) | Quadrático — ruim em listas grandes | BubbleSort, dois loops aninhados |
O(2ⁿ) | Exponencial — proibitivo | Força bruta em problemas combinatórios |
Ordenar 1 milhão de itens com BubbleSort (O(n²)) leva minutos; com QuickSort (O(n log n)) leva milissegundos. Mesmo input, mesma máquina — só muda o algoritmo.
A história costuma ser contada como uma linha reta: máquina → estruturada → orientada a objetos. Mas a evolução foi vários paradigmas em paralelo, cada um resolvendo o problema do seu jeito.
| Paradigma | Ideia central | Linguagens |
|---|---|---|
| Imperativo / Procedural | Sequência de comandos que mudam estado | C, Pascal, FORTRAN |
| Orientado a Objetos | Dados + comportamento juntos em classes | Smalltalk (1972), C++, Java |
| Funcional | Funções puras, sem estado mutável | Lisp (1958), Haskell, Erlang |
| Lógico | Você declara fatos e regras; a máquina deduz a resposta | Prolog (1972) |
| Declarativo | Diz o que quer, não como obter | SQL (1974), HTML |
Por décadas, OO dominou. Mas a partir de 2010 o estilo funcional voltou forte — Java 8 ganhou lambdas e Stream, JavaScript adotou map/filter/reduce, Kotlin e Scala misturam OO com funcional.
// estilo procedural
int total = 0;
for (Pedido p : pedidos) {
if (p.isPago()) {
total += p.getValor();
}
}
// estilo funcional (Java 8+)
int total = pedidos.stream()
.filter(Pedido::isPago)
.mapToInt(Pedido::getValor)
.sum();
Os dois fazem a mesma coisa, mas o segundo expressa a intenção, não o passo a passo. É a mesma onda do SQL — você diz "me dá os pagos", não "percorra a lista um por um".
Conforme os sistemas cresceram (anos 80/90), ficou claro que escrever um algoritmo que funciona não basta — ele precisa ser legível, testável e modificável. Surgem livros e movimentos focados em qualidade de código.
| Ano | Marco | Contribuição |
|---|---|---|
| 1972 | Smalltalk | Primeira linguagem 100% orientada a objetos. Define os conceitos de classe, objeto, mensagem, herança. |
| 1994 | Design Patterns (Gang of Four) | 23 padrões reutilizáveis pra problemas recorrentes em OO: Singleton, Factory, Observer, Strategy, etc. |
| 1999 | Refactoring (Martin Fowler) | Catalogou 70+ refatorações com nome próprio: Extract Method, Rename Variable, Replace Conditional with Polymorphism. |
| 1999 | TDD (Kent Beck) | Escrever o teste antes do código. Ciclo "red → green → refactor". |
| 2000s | SOLID (Robert Martin) | 5 princípios pra OO escalável: SRP, OCP, LSP, ISP, DIP. |
| 2008 | Clean Code (Robert Martin) | Síntese de tudo acima — nomes claros, funções pequenas, sem comentários redundantes, testes confiáveis. |
Antes: "se compila e roda, tá bom". Depois: código é lido 10x mais vezes do que escrito — e o leitor é você daqui a 6 meses, ou um colega novo. O algoritmo continua sendo o mesmo, mas como ele é expresso ganha tanta importância quanto se ele funciona.
// "funciona" mas é difícil de ler
public boolean v(User u) {
return u != null && u.s == 1 && u.t > 0;
}
// Clean Code — o nome conta a história
public boolean isUserActive(User user) {
return user != null
&& user.getStatus() == STATUS_ACTIVE
&& user.getRemainingTokens() > 0;
}
| Era | Período | Marco |
|---|---|---|
| 1. Pré-computador | 300 a.C. – 1936 | Euclides → Al-Khwarizmi → Lovelace → Turing |
| 2. A máquina nua | 1940s | Linguagem de máquina, Assembly |
| 3. Estruturadas | 1957 – 1972 | FORTRAN → ALGOL (for/while/if) → C |
| 4. Algoritmos como ciência | 1968+ | Knuth, estruturas de dados, Big O |
| 5. Outros paradigmas | 1958+ | Lisp (funcional), Prolog (lógico), SQL (declarativo) |
| 6. OO e qualidade | 1972 – 2008 | Smalltalk → GoF → Refactoring → SOLID → Clean Code |
Cada era resolveu um problema da anterior: máquina nua era impraticável → estruturadas. Estruturadas viraram caóticas em sistemas grandes → OO. OO virou bagunçada → Clean Code. A próxima era já está em curso (IA gerando código), e provavelmente vai cobrar a próxima conta.