⚡ Aula 04 — Projeto de Algoritmos, Complexidade e Notação Assintótica Big-O
Navegação Rápida
📍 Disciplina: 02 Pensamento Computacional | 🗺️ Área: 06 Computação e Telecomunicações | 🏠 Hub Principal ⬅️ Aula Anterior: Aula 03 - Abstração e Modelagem Computacional | ➡️ Próxima Aula: Aula 05 - Representação Digital da Informação
📌 Sumário da Aula
- 🧠 1. Fundamentos do Projeto de Algoritmos
- 📐 2. Notação Assintótica Formal: Big-O, Big-Omega e Big-Theta
- 📈 3. Classes Canônicas de Complexidade Temporal e Espacial
- 🗺️ 4. Algoritmos em Grafos Elétricos: Dijkstra e Árvore Geradora Mínima
- 📊 5. Diagrama de Notação Assintótica e Algoritmo de Dijkstra
- 📝 6. Questões de Concursos e Problemas Avançados Resolvidos
- 🔗 7. Conexões e Referências Cruzadas
🧠 1. Fundamentos do Projeto de Algoritmos
O quarto pilar do Pensamento Computacional é o Projeto de Algoritmos (Algorithm Design). Um algoritmo é definido formalmente como uma sequência finita, ordenada, não ambígua e mecanicamente executável de instruções de transformação lógica que recebe um conjunto de entradas válidas e produz uma saída determinística em tempo finito.
Para que um procedimento computacional seja considerado um algoritmo válido em engenharia, ele deve atender estritamente a cinco postulados fundamentais:
- Finitude: O processo deve terminar após um número contável e limitado de passos de execução.
- Definição / Não Ambiguidade: Cada instrução deve ser perfeitamente clara, sem margem a interpretações dúbias pela unidade de processamento.
- Entradas Bem Definidas: O domínio das grandezas de entrada deve ser explicitado (por exemplo, tensões nodais ).
- Saídas Determinísticas: Deve produzir os resultados esperados associados às entradas dadas (por exemplo, fluxos de potência nos ramos ).
- Efetividade: Todas as operações matemáticas e lógicas devem ser suficientemente básicas para que possam, em princípio, ser executadas exatamente por um agente computacional com recursos físicos limitados.
📐 2. Notação Assintótica Formal: Big-O, Big-Omega e Big-Theta
A eficiência de um algoritmo não deve ser medida em segundos ou milissegundos absolutos de relógio, pois o tempo de parede (wall-clock time) varia dramaticamente em função da velocidade de clock da CPU, da tecnologia do compilador e da carga do sistema operacional.
A análise de algoritmos quantifica o consumo de operações fundamentais e de memória como uma função puramente matemática do tamanho da entrada quando (comportamento assintótico).
flowchart LR BigO["Notação Big-O: O(g(n))<br/>Limite Superior Assintótico<br/>Pior Cenário Garantido"] BigTheta["Notação Big-Theta: Θ(g(n))<br/>Limite Justo / Exato<br/>Comportamento Assintótico Estrito"] BigOmega["Notação Big-Omega: Ω(g(n))<br/>Limite Inferior Assintótico<br/>Melhor Cenário Possível"] BigTheta --> BigO BigTheta --> BigOmega
2.1 Notação Big-O () — Limite Superior Assintótico
Dadas as funções e definidas sobre os inteiros positivos, diz-se que se e somente se existirem constantes reais positivas e tais que:
Significado em Engenharia: Estabelece o teto de pior caso (worst-case upper bound). O algoritmo tem a garantia matemática de que jamais consumirá mais tempo de execução do que uma função proporcional a para entradas suficientemente grandes.
2.2 Notação Big-Omega () — Limite Inferior Assintótico
Diz-se que se e somente se existirem constantes reais positivas e tais que:
Significado em Engenharia: Estabelece o piso assintótico (lower bound). Nenhum algoritmo que resolva essa classe de problemas poderá ter um tempo menor que .
2.3 Notação Big-Theta () — Limite Assintótico Estrito
Diz-se que se e somente se estiver simultaneamente contida em e . Isto é, existem constantes e tais que:
Significado em Engenharia: A função descreve perfeitamente a taxa de crescimento assintótico do algoritmo, sem folgas superiores ou inferiores.
📈 3. Classes Canônicas de Complexidade Temporal e Espacial
A tabela a seguir sumariza a hierarquia assintótica, exemplificada com problemas clássicos de Engenharia Elétrica:
| Classe de Complexidade | Notação Assintótica | Taxa de Crescimento para | Aplicação Típica em Engenharia Elétrica |
|---|---|---|---|
| Constante | operação | Verificação de estado lógico de disjuntor em relé IED; leitura em tabela hash indexada | |
| Logarítmica | operações | Busca binária de ponto de operação ótimo em tabela de calibração ordenada | |
| Linear | operações | Varredura de telemetria de sensores de temperatura de transformador; cálculo de corrente RMS | |
| Linear-Logarítmica | operações | Transformada Rápida de Fourier (FFT de Cooley-Tukey); ordenação de eventos cronológicos | |
| Quadrática | operações | DFT ingênua em sinais elétricos; multiplicação matricial densa ingênua; comparação par a par | |
| Cúbica | operações | Eliminação de Gauss-Jordan para inversão de matrizes cheias sem esparsidade | |
| Exponencial | operações | Despacho Unitário Hidrotérmico exaustivo (Unit Commitment); alocação combinatória exata |
🗺️ 4. Algoritmos em Grafos Elétricos: Dijkstra e Árvore Geradora Mínima
4.1 Algoritmo de Dijkstra para Caminhos de Impedância Mínima
Em redes de distribuição urbanas interligadas, quando ocorre uma falta permanente (curto-circuito trifásico), o sistema de automação de rede (Self-Healing) deve isolar o trecho avariado e encontrar o caminho de menor impedância elétrica ou menor perda Joule para reenergizar os clientes sadios através de alimentadores adjacentes.
Dado um grafo elétrico ponderado onde os pesos das arestas representam as resistências em ohms dos ramos:
flowchart TD Init["1. Inicialização<br/>d(s) = 0 para a subestação de origem s<br/>d(v) = ∞ para todas as demais barras v ≠ s<br/>Conjunto Q = V (todas as barras não visitadas)"] --> MinNode["2. Extrair Mínimo de Q<br/>u = nó em Q com menor distância d(u) estimada"] MinNode --> LoopArestas["3. Relaxamento das Arestas Adjacentes<br/>Para cada vizinho v de u:"] LoopArestas --> Rel{"d(u) + w(u,v) < d(v)?"} Rel -- Sim --> Atualiza["d(v) = d(u) + w(u,v)<br/>predecessor(v) = u"] Rel -- Não --> ProxViz["Manter d(v)"] Atualiza --> Remov["Remover u de Q"] ProxViz --> Remov Remov --> Cond{"Q está vazio?"} Cond -- Não --> MinNode Cond -- Sim --> Fim["Árvore de Caminhos Mínimos Calculada"]
Equação de Relaxamento de Arestas
Complexidade Computacional de Dijkstra:
- Implementação com Vetor Simples:
- Implementação Otimizada com Fila de Prioridade (Min-Heap Binário): A extração do nó mínimo custa executada vezes, e a atualização de chave (decrease-key) custa executada no máximo vezes:
Para uma rede de distribuição metropolitana com nós e ramos:
- Implementação ingênua: operações;
- Implementação com Min-Heap: operações — uma aceleração de vezes, permitindo recomposição automática em menos de .
4.2 Árvore Geradora Mínima (MST) no Planejamento de Cabeamento
Ao projetar a interligação de turbinas eólicas em um parque eólico offshore até a subestação coletora central, deseja-se minimizar o comprimento total de cabos submarinos isolados de média tensão ().
Esse problema é modelado como a busca da Árvore Geradora Mínima (Minimum Spanning Tree - MST) de um grafo não direcionado conexo. Os dois algoritmos fundamentais são:
- Algoritmo de Kruskal: Baseado em ordenação gulosa das arestas e detecção de ciclos através da estrutura de dados de Conjuntos Disjuntos (Union-Find com compressão de caminhos). Complexidade: .
- Algoritmo de Prim: Cresce uma árvore conectada a partir de um vértice raiz selecionando a aresta de corte de menor peso. Complexidade: usando Fibonacci Heap.
📊 5. Diagrama de Notação Assintótica e Algoritmo de Dijkstra
O diagrama abaixo, elaborado na estética Catppuccin Mocha, ilustra visualmente a taxonomia da notação Big-O e a mecânica de relaxamento do algoritmo de Dijkstra:
📝 6. Questões de Concursos e Problemas Avançados Resolvidos
Questão 1 (Banca CESPE/CEBRASPE - Engenheiro de Redes e Telecomunicações)
Considere dois algoritmos e desenvolvidos para processamento de transitórios eletromagnéticos em linhas de transmissão contendo pontos de amostragem no tempo:
- O algoritmo requer exatamente operações;
- O algoritmo requer exatamente operações.
Determine o valor limite de a partir do qual o algoritmo torna-se rigorosamente mais rápido do que o algoritmo e avalie suas respectivas complexidades assintóticas na notação Big-O.
Resolução Passo a Passo:
-
Complexidades Assintóticas:
- Para :
- Para :
-
Ponto de Cruzamento (): Para , dividem-se ambos os lados por :
Testando valores inteiros de :
- Para :
- Para :
Refinando a busca entre 400 e 500:
- Para :
- Para :
- Para :
Portanto, para , tem-se .
Análise Crítica: Embora para pequenas janelas amostrais () a constante elevada de () o torne mais lento que (), a taxa de crescimento linear-logarítmica de supera assintoticamente o crescimento quadrático de . Para um milhão de amostras (), executa operações, enquanto exigiria operações (mil vezes mais lento).
Questão 2 (Banca VUNESP - Engenharia de Automação / Concurso Público)
Um sistema computacional embarcado em um relé de proteção digital realiza a busca de faltas em um banco de registros históricos de oscilografia contendo registros ordenados cronologicamente. Um estagiário de engenharia implementou inicialmente uma busca linear sequencial. O engenheiro sênior substituiu esse código por uma busca binária clássica. Se o banco de dados armazena registros, qual é o número máximo de comparações no pior caso para cada algoritmo?
Resolução Passo a Passo:
-
Busca Linear Sequencial (): No pior caso (o elemento procurado está na última posição ou não pertence ao vetor), o algoritmo compara o registro com cada um dos elementos:
-
Busca Binária (): A cada iteração, a busca binária divide o espaço de busca pela metade. O número máximo de comparações no pior caso é dado por: Como :
Conclusão: A otimização algorítmica reduziu o esforço de processamento de mais de um milhão de acessos à memória para apenas 21 passos discretos, permitindo a atuação do relé em frações infinitesimais de microssegundo.
Questão 3 (Problema Prático de Engenharia - Algoritmo de Dijkstra em Malha Elétrica)
Considere uma microrrede elétrica contendo 4 barras e as seguintes resistências de condutores entre as barras conectadas:
- Ramo :
- Ramo :
- Ramo :
- Ramo :
- Ramo :
Determine o caminho de menor resistência ôhmica total partindo da Barra 1 (gerador) até a Barra 4 (carga crítica) através do algoritmo de Dijkstra passo a passo.
Resolução Passo a Passo:
-
Inicialização:
- , , , .
- Predecessores: .
- .
-
Iteração 1:
- Vértice com menor em : ().
- Relaxar vizinhos de 1:
- Vizinho 2: , .
- Vizinho 3: , .
- Remover 1 de . Estado: , com .
-
Iteração 2:
- Vértice com menor em : ().
- Relaxar vizinhos de 3:
- Vizinho 2: (relaxamento realizado!) , .
- Vizinho 4: , .
- Remover 3 de . Estado: , com .
-
Iteração 3:
- Vértice com menor em : ().
- Relaxar vizinhos de 2:
- Vizinho 4: (relaxamento realizado!) , .
- Remover 2 de . Estado: , com .
-
Iteração 4:
- Vértice com menor em : (). Não há arestas saindo de 4 a relaxar.
- Remover 4 de . . Terminação.
-
Reconstrução do Caminho:
- .
Nota de Engenharia: Embora a aresta direta de 1 para 2 meça , o percurso passando pela barra intermediária 3 () resulta em apenas , ilustrando como o algoritmo encontra desvios elétricos com menor perda dissipativa total.
🔗 7. Conexões e Referências Cruzadas
Disciplinas Vinculadas:
- Aula 03: Teoria dos grafos elétricos e matrizes topológicas.
- Aula 05: Complexidade de algoritmos de processamento de imagens.
- 01 Lógica de Programação: Laços de repetição e complexidade ciclomática.
- 07 Planejamento e Análise de SEP: Algoritmos de Newton-Raphson e Fatoração LU de matrizes esparsas.
Materiais Didáticos Oficiais da Disciplina:
- Arquivo de Curso:
02 - Fundamentos de Softwares de Computadores.pdf - Arquivo de Curso:
05 - Noções de Programação - Exemplos Com Manipulação de Imagens Digitais.pdf - Arquivo de Prática:
07 - Praticando.pdf