Este documento apresenta conceitos fundamentais de análise de algoritmos, incluindo: (1) A importância de expressar o tempo de execução de um algoritmo independentemente da máquina, contando o número de passos como função do tamanho da entrada; (2) A notação Big-O para descrever a taxa de crescimento do tempo de execução em termos da entrada; (3) Exemplos comuns de notações Big-O como O(1), O(log n), O(n), O(n log n), O(n2), O(2n) e O(n!).
Este documento apresenta conceitos fundamentais de análise de algoritmos, incluindo: (1) A importância de expressar o tempo de execução de um algoritmo independentemente da máquina, contando o número de passos como função do tamanho da entrada; (2) A notação Big-O para descrever a taxa de crescimento do tempo de execução em termos da entrada; (3) Exemplos comuns de notações Big-O como O(1), O(log n), O(n), O(n log n), O(n2), O(2n) e O(n!).
Este documento apresenta conceitos fundamentais de análise de algoritmos, incluindo: (1) A importância de expressar o tempo de execução de um algoritmo independentemente da máquina, contando o número de passos como função do tamanho da entrada; (2) A notação Big-O para descrever a taxa de crescimento do tempo de execução em termos da entrada; (3) Exemplos comuns de notações Big-O como O(1), O(log n), O(n), O(n log n), O(n2), O(2n) e O(n!).
roberto.leminski@docente.unip.br Conteúdo •Tempo de execução de um Algoritmo
•Notação Grande-O Tempo de Execução •Expressar o tempo de execução em termos de passos básicos de computação é uma simplificação.
•O tempo gasto por um tal passo depende
crucialmente do processador em questão e mesmo de detalhes, tais como a estratégia de cache (que resulta em tempos sutilmente diferentes de uma execução para próxima). Tempo de Execução •Faz mais sentido buscar uma caracterização simples, independente da máquina, para a eficiência de um algoritmo.
•Assim sempre expressaremos o tempo de
execução contando o número de passos básicos de computação como uma função do tamanho da entrada. Tempo de Execução •Faz mais sentido buscar uma caracterização simples, independente da máquina, para a eficiência de um algoritmo.
•Assim sempre expressaremos o tempo de
execução contando o número de passos básicos de computação como uma função do tamanho da entrada. Tempo de Execução •Em vez de reportar que um algoritmo toma, digamos, 5n3 + 4n + 3 passos em uma entrada de tamanho n, é muito mais fácil deixar de fora termos de menor ordem, tais como 4n e 3.
•Mesmo o coeficiente 5 do termo de maior
ordem (os computadores serão 5 vezes mais rápidos de qualquer forma em poucos anos), e apenas dizer que o algoritmo toma tempo O(n3) Grande-O •Suponha que estejamos escolhendo entre dois algoritmos para determinada tarefa computacional.
•Um toma f1(n) = n2 passos, enquanto o
outro toma f2(n) = 2n + 20 passos. Qual é melhor?
•Depende do valor de n. Para n 5, n2 é
menor; depois disso, 2n + 20 é claramente melhor. Grande-O Grande-O Grande-O Grande-O • Exemplo: Determinar a função referente a um algoritmo para calcular o determinante de uma matriz.
•Considerar que as três operações levam
(multiplicação, adição e subtração) levam o mesmo tempo de execução. Grande-O • Exemplo: Determinar a função referente a um algoritmo para calcular o determinante de uma matriz.
•Considerar que as três operações levam
(multiplicação, adição e subtração) levam o mesmo tempo de execução. Grande-O Grande-O Grande-O - Exemplos • Em um algoritmo de complexidade O(n!) (fatorial) o número de instruções executadas cresce muito rapidamente para um pequeno crescimento do número de itens processados. Dentre os ilustrados, é o pior comportamento para um algoritmo, pois rapidamente o processamento se torna inviável. É o caso da implementação inocente do Problema do Caixeiro Viajante ou de um algoritmo que gere todas as possíveis permutações de uma lista. Grande-O - Exemplos •Um algoritmo de complexidade O(2n) (exponencial) também é ruim, pois o número de instruções também cresce muito rapidamente (exponencialmente), ainda que numa taxa menor do que o anterior. É o caso de algoritmos que fazem busca em árvores binárias não ordenadas.
•Um algoritmo de complexidade O(n2) (quadrático)
é factível, mas tende a se tornar muito ruim quando a quantidade de dados é suficientemente grande. É o caso de algorítmos que têm dois laços (for) encadeados, como, por exemplo, o processamento de itens em uma matriz bidimensional. Grande-O - Exemplos •Um algoritmo de complexidade O(n log n) (sub- quadrático ou super-linear) é melhor do que o quadrático, sendo geralmente até onde se consegue otimizar algoritmos que são quadráticos. É o caso do algoritmo de ordenação QuickSort, por exemplo (que tem essa complexidade no caso médio, mas que ainda assim é quadrático no pior caso).
•Um algoritmo de complexidade O(n) (linear) é
aquele cujo crescimento no número de operações é diretamente proporcional ao crescimento do número de itens. É o caso de algoritmos de busca em uma matriz unidimensional não ordenada, por exemplo. Grande-O - Exemplos •Um algoritmo de complexidade O(log n) (logaritmo) é aquele cujo crescimento do número de operações é menor do que o do número de itens. É o caso de algoritmos de busca em árvores binárias ordenadas por exemplo (no caso médio, no pior caso continua sendo linear).
•Um algoritmo de complexidade O(1) (constante) é
aquele em que não há crescimento do número de operações, pois não depende do volume de dados de entrada (n). É o caso do acesso direto a um elemento de uma matriz, por exemplo. Referências • DASGUPTA, Sanjoy. Christos Papadimitriou, Umesh Vazirani. Algoritmos. Porto Alegre, RS: AMGH, 2011. • StackOverflow https://pt.stackoverflow.com/questions/568 36/defini%C3%A7%C3%A3o-da-nota %C3%A7%C3%A3o-big-o Dúvidas ? Obrigado !