Crescimento de Funções PPGI/2009 Prof. Lucídio Cabral - Estrutura de Dados e Complexidade de Algoritmos 1 Análise de Algoritmos – tempo de processamento em função dos dados de entrada; – espaço de memória total requerido para os dados; – comprimento total do código; – correcta obtenção do resultado pretendido; – robustez (como comporta-se com as entradas inválidas ou não previstas). – quantidade de "trabalho" necessária para a sua execução, expressa em função das operações fundamentais, as quais variam de acordo com o algoritmo, e em função do volume de dados. Complexidade • Porquê o estudo da Complexidade? – Performance • Escolher entre vários algoritmos o mais eficiente para implementar; • Desenvolver novos algoritmos para problemas que já têm solução; • Desenvolver algoritmos mais eficientes (melhorar os algoritmos), devido ao aumento constante do "tamanho" dos problemas a serem resolvidos. – Complexidade Computacional - torna possível determinar se a implementação de determinado algoritmo é viável. Complexidade • Tipos de Complexidade – Espacial • Este tipo de complexidade representa, por exemplo, o espaço de memória usado para executar o algoritmo. – Temporal • Este tipo de complexidade é o mais usado podendo dividir-se em dois grupos: – Tempo (real) necessário à execução do algoritmo. (como podemos medir?) – Número de instruções necessárias à execução. Analise de Algoritmos • Medidas de Análise – Devem ser independentes da tecnologia (hardware/software) – Modelos Matemáticos simplificados baseados nos fatores relevantes: • Tempo de Execução Uma função que relaciona o tempo de execução com o tamanho de entrada: t = F(n) – Conjunto de operações a serem executadas. – Custo associado à execução de cada operação. • Ocupação de Espaço em Memória Complexidade • Exemplo – Sejam 5 algoritmos A1 a A5 para resolver um mesmo problema, de complexidades diferentes. (Supomos que uma operação leva 1 ms para ser efetuada.) – Tk(n) é a complexidade ou seja o número de operações que o algoritmo efetua para n entradas n 16 32 512 A1 A2 T1(n)= n T2(n)=nlog n 0.016s 0.032s 0.512s 0.064s 0.16s 9s tempo necessário para o algoritmo em função de n entradas A3 T3 (n)=n2 0.256s 1s 4m22s A4 T4 (n)=n3 4s 33s 1 Dia 13h A5 T5(n)=2n 1m4s 46 Dias 10137 Séculos Operações primitivas • • • • • • Atribuição de valores a variáveis Chamadas de métodos Operações aritméticas Comparação de dois números Acesso a elemento de um array Seguir uma referência de objeto (acesso a objeto) • Retorno de um método Complexidade de Algoritmos • Complexidade de pior caso – big-Oh O(g(n)) • Complexidade de melhor caso – big-Omega W(g(n)) – de uso bem menos freqüente – em algumas situações específicas • Complexidade de caso médio – big-Theta Q(g(n).) – menos utilizada apesar de importante – difícil conhecer a distribuição de probabilidades das diferentes entradas Notações assintóticas Q - Limite assintótico apertado ou exato O - Limite assintótico superior W - Limite assintótico inferior o - Limite superior que não é assintoticamente apertado w - Limite inferior que não é assintoticamente apertado Por que as notações assintóticas são importantes? • Elas fornecem uma caracterização simples da eficiência de um algoritmo. • Elas permitem a comparaçãode desempenho entre vários algoritmos. • Para valores elevados de componentes/entradas, as constantes multiplicativas e termos de baixa ordem de um tempo de execução exato são dominados pelo efeito do tamanho de entrada (o número de componentes). – O tempo de execução de uma algoritmo sobre uma entrada particular, é o número de operações primitivas ou “passos” executados. – O tamanho da entrada depende problema sendo estudado. Mas na maioria dos casos este é o número de itens na entrada, por exemplo: o número total de bits. Resumindo, em geral, quando observamos tamanhos de entrada suficientemente grandes para tornar a ordem de crescimento do tempo de execução relevante para um algoritmo, nós estamos estudando a eficiência assintótica de um algoritmo. E um algoritmo que é assintoticamente mais eficiente será efetivamente a melhor escolha. Isto pode não ser verdade para todas as entradas consideradas pequenas! Q - Limite assintótico apertado ou exato OBS: Q - Limite assintótico apertado ou exato Eg. Q - Limite assintótico apertado ou exato Eg. O - Limite assintótico superior O - Limite assintótico superior Qual melhor algoritmo? • Sejam A e B dois algoritmos que o resolvem o problema P, cujos tempos de execução são TA(n) e TB(n) • comportamento assintótico – tamanho da entrada arbitrariamente grande – caracterizado pela notação O (big O) Diagrama Definição do Big-Oh Ordens mais comuns 2n (exponencial) n2 (quadrática) n log n f n (linear) log n (logarítmica) 1 (constante) n Fonte: Sahni, "Data Structures, Algorithms and Applications in C++" Alguns conceitos • • • • • • • • T (n) = O (1) : constante T (n) = O (log log n) : super-rápido T (n) = O (log n) : logarítmico – muito bom T (n) = O (n) : linear – toda a entrada é visitada T (n) = O (n log n) : limite de muitos problemas T (n) = O (n2) : quadrático T (n) = O (nk) : polinomial no tamanho da entrada T (n) = O (kn), O (n!), O (nn) : exponencial – ruim! Teoremas 1. Comportamento assintótico da soma de duas funções cujos comportamentos assintóticos particulares são conhecidos: Se f1(n) = O(g1(n)) e f2(n) = O(g2(n)), então: f1(n) + f2(n) = O(max(g1(n)) , g2(n))) 2. O(k f(n)) = O(f(n)) 3. O(f(n)) O(g(n)) = O(f(n) g(n)) Eficiência de um Algoritmo, mais um exemplo Três algoritmo para calcular 1 + 2 + … n para um n > 0 Eficiência de um Algoritmo O(n) O(n2) O(1) Número de operações necessárias A notação O f(n) = 8n + 128 é O (n2)? f(n) c.n2 ? • Seja c =1 8n + 128 n2, então 0 n2 – 8n – 128 0 (n – 16)(n+8) n0 = 16 c =1, no = 16, f (n) c.n2 para todo n n0 A notação O • A função atua como um limite superior assintótico da função f – f = n2 -1 f = O(n2) – f = n2 -1 f = O(n3) – f = 403 f = O(1) – f = 5+2logn +3log2n f= O(log2n) – f = 5+2 log n +3log2n f = O(n) – f = 5.2n +5n10 f = O(2n) W - Limite assintótico inferior o - Limite superior que não é assintoticamente apertado w - Limite inferior que não é assintoticamente apertado Notações assintóticas em equações Relações de Funções Assintóticas Limites podem ser usados para determinar a ordem de complexidade c então f (n) = Q ( g (n)) se c > 0 se lim f (n) / g (n) = 0 or c > 0 então f (n) = o ( g(n)) n or c > 0 então f (n) = W ( g (n)) Exemplo usando limites 5n 3n W(n ) dado que , 3 2 5n 3n 5n 3n lim lim 2 lim 2 2 n n n n n n 3 3 Regra de L’Hopital Se f(x) e g(x) são ambas funções diferenciáveis com derivadas f’(x) e g’(x), respectivamente, e se lim g ( x) lim f ( x) então x x f ( x) f ' ( x) lim lim x g ( x ) x g ' ( x ) sempre que o limite a direita existe Exemplos usando limites 10n 3 - 3n Q(n 3 ) dado que , 10n 3 - 3n 10n 3 3n lim lim 3 - lim 3 10 3 n n n n n n n log e n O (n 2 ) dado que , n log e n log e n lim lim ? Use a Regra de L' Hopital 2 n n n n (log e n)' 1/ n lim lim 0 n n 1 (n)' Exemplo usando limites lg n O (n ) ln n lg n ln 2 ln n 1 (lg n)' '= ln 2 nln2 lg n (lg n)' 1 lim lim 0 lim n n n n n ln 2 n' Exemplo usando limites n k O (2n ) onde k é uma constante inteira positiva 2 n e n ln 2 n ln 2 n ln 2 n ( 2 )' (e )'= ln2 e 2 ln 2 n - nk kn k 1 lim n lim n n 2 n 2 ln 2 k -2 k ( k 1)n k! lim ... lim n k 0 2 n n n 2 ln 2 2 ln 2