Quantidade de memria necessria Um algoritmo que usa 1MB de memria RAM melhor que outro que usa 1GB Medir o tempo gasto por um algoritmo No uma boa opo Depende do compilador Pode preferir algumas construes ou otimizar melhor Depende do hardware GPU vs. CPU, desktop vs. smartphone
Estudar o nmero de vezes que operaes so executadas Achar o mximo de um vetor
Complexidade: f(n) = n-1 Esse algoritmo timo int vmax(int *vec, int n) { int i; int max = vec[0]; for(i = 1; i < n; i++) { if(vec[i] > max) { max = vec[i]; } } return max; } - - 1 n-1 n-1 A < n-1 n-1 n-1 1 Anlise de complexidade feita em funo de n n indica o tamanho da entrada Nmero de elementos no vetor Nmero de vrtices num grafo Nmero de linhas de uma matriz Diferentes entradas podem ter custo diferente Melhor caso Pior caso Caso mdio Recuperar um registro num arquivo procurando sequencialmente Quantos registros precisam ser processados em uma busca? Melhor caso: f(n) = 1 Pior caso: f(n) = n Caso mdio: f(n) = (n+1)/2 Supondo que registros procurados esto presentes no arquivo e que registros so pesquisados com a mesma probabilidade
Problema: encontrar o valores minimo e mximo em um vetor void minmax(int *vec, int n, int *min, int *max) { int i; int *min = vec[0]; int *max = vec[0]; for(i = 1; i < n; i++) { if(vec[i] < *min) { *min = vec[i]; } if(vec[i] > *max) { *max = vec[i]; } } } - - 1 1 n-1 n-1 A < n-1 - n-1 B < n-1 - - - melhor caso: f(n) = 2(n-1) pior caso: f(n) = 2(n-1) caso mdio: f(n) = 2(n-1) Se vec[i] < *min, ento no precisamos checar se vec[i] > *max void minmax2(int *vec, int n, int *min, int *max) { int i; int *min = vec[0]; int *max = vec[0]; for(i = 1; i < n; i++) { if(vec[i] < *min) { *min = vec[i]; } else { if(vec[i] > *max) { *max = vec[i]; } } } } - - 1 1 n-1 n-1 A < n-1 - n-1-A B < n-1-A - - - - melhor caso: (decrescente) f(n) = n-1 pior caso: (crescente) f(n) = 2(n-1) caso mdio: (aleatrio) f(n) > 3(n-1)/2 Comparar elementos par-a-par Custo: n/2 comparaes
Comparar elementos par-a-par Custo: n/2 comparaes Elementos vermelhos so maiores que os azuis Encontrar o mximo entre os elementos vermelhos Custo: n/2 comparaes Encontrar o mnimo entre os elementos azuis Custo: n/2 comparaes
void minmax3(int *vec, int n, int *min, int *max) { int i; int *min = INT_MAX; int *max = INT_MIN; for(i = 0; i < n; i += 2) { if(vec[i] < vec[i+1]) { a = i; v = i+1; } else { a = i+1; v = i; } if(vec[a] < *min) *min = vec[a]; if(vec[v] > *max) *max = vec[v]; } } - - 1 1 n/2 n/2 n/4 - n/4 - n/2 A < n/2 n/2 B < n/2 - - melhor caso: f(n) = 3n/2 pior caso: f(n) = 3n/2 caso mdio: f(n) = 3n/2 Algoritmo timo Algoritmo f(n) Melhor caso Pior caso Caso mdio MinMax1 2(n-1) 2(n-1) 2(n-1) MinMax2 n-1 2(n-1) > 3(n-1)/2 MinMax3 3n/2 3n/2 3n/2 Para valores suficientemente pequenos de n, qualquer algoritmo custa pouco para ser executado, mesmo os ineficientes Escolha de um algoritmo no um problema crtico Logo, analisamos algoritmos para grandes valores de n Estudamos o comportamento assinttico das funes de complexidade de um programa (comportamento pra grandes valores de n) Uma funo f(n) domina assintoticamente outra funo g(n) se existem duas constantes positivas c e m tais que, para n m , temos |g(n)| c|f(n)|. f(n) = n 2 , g(n) = n
f(n) domina assintoticamente g(n) c = 1, m = 0
|g(n)| 1|f(n)| para todo n m = 0
f(n) = n 2 , g(n) = (n+1) 2
f(n) e g(n) dominam assintoticamente uma outra
|f(n)| 1|g(n)| para todo n m = 0
|g(n)| 4|f(n)| para todo n m = 1 Definimos g(n) = O(f(n)) se f(n) domina assintoticamente g(n) L se g(n) da ordem no mximo f(n) Quando dizemos que o tempo de execuo de um programa T(n) = O(n 2 ), existem constantes c e m tais que T(n) cn 2 para n m f(n) = (n+1) 2 = O(n 2 ) Pois (n+1) 2 4n 2 , para n m = 1
f(n) = n 2 e g(n) = n n = O(n 2 ), (faa m = 0 e c = 1) Mas n 2 no O(n) Suponha que existam c e m tais que para todo n m, n 2 cn Logo n c para todo n m, contradio f(n) = 3n 3 + 2n 2 + n = O(n 3 ) Basta mostrar que f(n) 6n 3 , para n m = 0 Podemos dizer que f(n) = 3n 3 + 2n 2 + n = O(n 4 ), mas essa afirmao mais fraca que f(n) = O(n 3 )
f(n) = log 5 (n) = O(log(n)) log b (n) difere de log c (n) por uma constante log b (c) f(n) log 5 (e)log(n), para todo n m = 0 Imagine um programa com trs fases A primeira com custo O(n) A segunda com custo O(n 2 ) A terceira com custo O(n log(n))
Aplicando a regra da soma O tempo de execuo total do programa O(n 2 )
Uma funo g(n) (f(n)) se g(n) domina assintoticamente f(n) Notao O denota um limite superior e a notao denota um limite inferior
f(n) = 3n 3 + 2n 2 + n = (n 3 ) Basta mostrar que n 3 3n 3 + 2n 2 + n, para n m = 0 Podemos dizer que f(n) = 3n 3 + 2n 2 + n = (n 2 ), mas essa afirmao mais fraca que f(n) = (n 3 ) Uma funo g(n) (f(n)) se g(n) e f(n) dominam assintoticamente uma outra Definio equivalente: g(n) = (f(n)) se g(n) = O(n) e g(n) = (f(n)) Notao O um limite assinttico firme Diz que duas funes crescem de forma similar e que a diferena constante Prove que 4log 2 (n) + 16 = O(n) 4log 2 (n) + 16 n para n m = 64 = 2 6
Prove que 4log 2 (n) + 16 = O(log 2 n) 4log 2 (n) + 16 5log 2 (n) para n m = 2 17
2 n+1 = O(2 n ). Verdadeiro ou falso? Verdadeiro, faa c = 2 e m = 0 2 2n = O(2 n ). Verdadeiro ou falso? Falso. Prova: Suponha 2 2n c2 n , divida por 2 n e obtenha 2 n c
Por que falar o tempo de execuo do algoritmo A pelo menos O(2 n ) no faz sentido? Um algoritmo com tempo de execuo O(2 n ) realiza no mximo c2 n operaes. Falar que um algoritmo realiza pelo menos no mximo c2 n operaes no faz sentido.
Prove que max(f(n), g(n)) = (f(n) + g(n)) max(f(n), g(n)) 1(f(n) + g(n)) para n m = 0 max(f(n), g(n)) (1/2)(f(n) + g(n)), para n m = 0
Se f uma funo de complexidade para um algoritmo, ento O(f) considerada a complexidade assinttica do algoritmo Podemos comparar algoritmos usando suas complexidades assintticas Um algoritmo O(n) melhor do que um O(n 2 ) Algoritmos com a mesma complexidade assinttica so equivalentes s vezes, a constante da funo de complexidade de um algoritmo importar Um algoritmo com complexidade 2n 2 melhor do que um com complexidade 100n para valores de n menores que 50 Quando dois algoritmos tm a mesma complexidade assinttica, podemos desempatar usando a constante da funo de complexidade Complexidade constante Tempo de execuo do algoritmo independe do tamanho da entrada Os passos do algoritmo so executados um nmero fixo de vezes
Exemplo: determinar se um nmero mpar Complexidade logartmica Tpico de algoritmos que dividem um problema transformando-o em problemas menores (dividir para conquistar) Tempo de execuo pode ser considerado menor do que uma constante grande Quando n um milho, log(n) 20 A base do logartmo tem impacto pequeno Exemplo: busca binria Complexidade linear O algoritmo realiza um nmero fixo de operaes sobre cada elemento da entrada Melhor situao para um algoritmo que processa n elementos de entrada e produz n elementos de sada
Exemplo: busca sequencial, calcular fatorial Tpico de algoritmos que dividem um problema em subproblemas, resolve cada subproblema de forma independente, e depois combina os resultados
Exemplo: ordenao (eficiente) Complexidade quadrtica Tpico de algoritmos que operam sobre pares dos elementos de entrada Comumente em um anel dentro de outro til para resolver problemas de tamanhos relativamente pequenos
Exemplos: ordenao (ineficiente), imprimir uma matriz Complexidade cbica til para resolver problemas pequenos
Exemplo: multiplicao de matrizes Complexidade exponencial Tpicos de algoritmos que fazem busca exaustiva (fora bruta) para resolver um problema No so teis do ponto de vista prtico Quando n 20, O(2 n ) um milho Complexidade exponencial Pior do que O(c n ) No so teis do ponto de vista prtico Quando n 20, O(n!) maior que 2 quintilhes
(tamanho) Algoritmo polinomial no tempo de execuo tem funo de complexidade O(f(n)), onde f(n) um polinmio Algoritmos polinomiais geralmente so obtidos atravs de um entendimento mais profundo da estrutura do problema Enquanto algoritmos exponenciais so tpicos de solues fora bruta Um problema considerado Intratvel: se no existe algoritmo polinomial para resolv-lo Bem resolvido: se existe algoritmo polinomial para resolv-lo Existem algoritmos de complexidade exponencial que so teis Por exemplo, o algoritmo simplex tem pior caso de tempo de execuo exponencial, mas na mdia executa muito mais rpido do que isso Infelizmente, estas excees so incomuns e a maioria dos algoritmos exponenciais conhecidos no so muito teis Um caixeiro viajante deseja visitar n cidades de tal forma que sua viagem inicie e termine em uma mesma cidade Cada cidade deve ser visitada uma nica vez Duas cidades i, j podem ser ligadas por uma estrada de comprimento c i,j O problema encontrar a menor rota para a viagem
A figura abaixo mostra 4 cidades (c1, c2, c3 e c4) e os pesos nas arestas mostram os comprimentos de cada estrada
O percurso c1, c3, c4, c2, c1 a soluo para o problema, cujo percurso total tem distncia 24 Um algoritmo simples seria verificar todas as rotas e escolher a menor delas H (n - 1)! rotas possveis e a distncia total percorrida em cada rota envolve n adies, logo o nmero total de adies n! No exemplo anterior teramos 24 adies; se tivssemos 50 cidades, o nmero de adies seria aproximadamente 10 64
Em um computador que executa 10 9 adies por segundo, o tempo total para resolver o problema com 50 cidades seria maior do que 10 45 sculos s para executar as adies Determinar o tempo de execuo de um algoritmo pode ser complexo Determinar a complexidade assinttica, sem preocupao com as constantes envolvidas, pode ser uma tarefa mais simples Anlise de algoritmos utiliza tcnicas de matemtica discreta Manipulao de somas, produtos, permutaes, coeficientes binomiais, equaes de recorrncia
Comando simples (atribuio, comparao, operao aritmtica, acesso a memria): O(1) Sequncia de comandos: mximo dos tempos de execuo dos comandos Comando condicional: tempo dos comandos dentro do condicional mais o tempo pra testar a condio, que O(1) Anel: Tempo de execuo dos comandos do anel mais teste de parada (geralmente O(1)), multiplicado pelo nmero de iteraes Para funes no recursivas: Comece pelas funes que no chamam nenhuma outra funo Depois analise funes que chamam apenas funes analisadas no passo anterior E assim sucessivamente at chegar ao programa principal (main)
Qual a funo de complexidade do nmero de atribuies para o acumulador? Qual a ordem de complexidade da funo soma_acumulada? int soma_acumulada(int n) { int i; int acumulador = 0; for(i = 0; i < n; i++) { acumulador += i; } return acumulador; } - - 1 n n - 1 -
Qual a complexidade assinttica da funo exemplo? void exemplo(int n) { int i, j; int a = 0; for(i = 0; i < n; i++) for(j = n; j > i; j--) a += i + j; exemplo1(n); } - - - 1 n ? ? 1 - - - - 1 n n(n+1)/2 n(n+1)/2 1 - Encontre o menor valor no vetor Troque-o com o primeiro elemento V[0] Repita os passos acima com os n-1 itens restantes, depois com os n-2 restantes, at que reste apenas 1
void ordena(int *V, int n) { int i, j, min, x; for(i = 0; i < n - 1; i++) { min = i; for(j = i + 1; j < n; j++) if(V[j] < V[min]) min = j; /* troca A[min] e A[i]: */ x = V[min]; V[min] = V[i]; V[i] = x; } } - - n-1 n-1 ? ? ? - n-1 n-1 n-1 - - - - n-1 n-1 n(n-1)/2 n(n-1)/2 A < n(n-1)/2 - n-1 n-1 n-1 - - Qual a complexidade assinttica do nmero de comparaes? // A, B e C sao vetores globais void e1(int n) { int i, j, k; for(i = 0; i < n; i++) for(j = 0; j < n; j++) { C[i][j] = 0; for(k = n-1; k >= 0; k--) { C[i][j] = C[i][j] + A[i][k] * B[k][j]; } } } } O que faz essa funo? Qual sua complexidade assinttica? - - - n n*n n*n n*n*n n*n*n
- - - - void e2(int n) { int i, j, x, y; x = y = 0; for(i = 1; i <= n; i++) { for(j = i; j <= n; j++) x = x + 1; for(j = 1; j < i; j++) y = y + 1; } } - - - 1 n n(n+1)/2 n(n+1)/2 n(n-1)/2 n(n-1)/2 - -