Buscar

Tema 1 - Complexidade de Algoritmos

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 45 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 45 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 45 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Soler 
 A avaliação de desempenho de um algoritmo 
quanto executado por um computador pode 
ser feita a posteriori ou a priori. 
◦ A posteriori: mede o tempo de execução 
propriamente dito. 
 Arquitetura 
 Linguagem 
 Código 
◦ Benchmarks 
◦ A priori: feita sem sua execução. 
 Considera itens de entrada 
 Número de instruções executadas 
 O aspecto importante da entrada é seu 
“tamanho”, que pode ser dado como 
número de valores num vetor, o número de 
registros num arquivo, etc. 
◦ O tempo de execução de um algoritmo pode ser 
dado como uma função T(n) do tamanho n da sua 
entrada. 
 Por exemplo, um programa pode ter tempo 
de execução T(n) = n. 
 A unidade de T(n) é em principio instrução 
executada. 
 Uma instrução neste contexto é uma 
seqüência de operações cujo tempo de 
execução pode ser considerado constante 
(de certa forma, cada “passo” do algoritmo). 
 Por exemplo, o algoritmo a abaixo: 
 
 public void somavetor (int v[n]) { 
int k=0; 
for (int i=0; i<v.length; i++) 
 k = k + v[i]; 
 } 
 
 Sendo v a entrada, de tamanho n, pode-se 
ver facilmente que a soma k+v[i] será 
efetuada n vezes. 
 
 Conseqüentemente, T(n) = n, incluindo o 
passo de inicialização. O tempo de 
execução (em instruções) variará conforme 
variar n, numa proporção linear. 
 
 No entanto o tempo de execução também 
irá variar de acordo com outros fatores. 
public int localiza (int v[n], int x){ 
 
for (int i=0; i<v.length; i++){ 
 if (x==v[i]) 
 return i; 
} 
return -1; 
} 
 
 T(n) = n + 1 
 O teste pode ser executado apenas uma 
vez, se o valor procurado estiver no 
primeiro elemento do vetor. 
 
 É executado no máximo n vezes. 
 
 Pode-se cogitar, então, de tempos 
mínimos, médios e máximos. 
 Acontece que, em geral: 
◦ tempos mínimos são de pouca utilidade 
◦ tempos médios são difíceis de calcular 
(dependem de se conhecer a probabilidade de 
ocorrência das diferentes entradas para o 
algoritmo). 
 
 Considera-se assim T(n) como uma medida 
assintótica máxima, ou seja, uma medida 
do pior caso de desempenho, que ocorre 
com a entrada mais desfavorável possível. 
public int localiza (int v[n], int x){ 
for (int i=0; i<v.length; i++){ 
 if (x==v[i]) 
 return i; 
} 
return -1; 
} 
 No caso anterior, T(n) = n + 1, incluindo o 
passo de retorno, que sempre acontece 
uma vez. 
 
 A avaliação analítica de uma algoritmo pode 
ser feita com vistas a se obter uma 
estimativa do esforço de computação. 
 
 Não em termos de unidade de tempo 
propriamente, mais em termos de uma taxa 
de crescimento do tempo de execução em 
função do “tamanho do problema”, i.e., do 
tamanho da entrada. 
 
◦ Ex: algoritmos de ordenação 
 Pode se considerar o comportamento de dois 
algoritmos, A1 e A2, que realizam a mesma tarefa 
em tempos TA1 e TA2, para uma entrada de 
tamanho n. observemos os tempos de execução 
para diferentes tamanhos da entrada: 
 Conclusão: ao se multiplicar o tamanho da entrada 
por k, o tempo de A1 cresceu segundo k e o de A2 
segundo k². 
 
 Ou seja, a taxa de crescimento do tempo de 
execução de A1 é proporcional a n, e a de A2, 
proporcional a n². 
 Essa taxa de crescimento proporcional é chamada 
complexidade do algoritmo. 
 
 Ela permite uma classificação dos algoritmos 
segundo sua categoria de complexidade e permite 
também comparar qualitativamente algoritmos 
diferentes que realizam a mesma tarefa. 
 
 Pode ser considerada em termos de tempo de 
execução (complexidade de tempo) ou termos de 
espaço de memória utilizado (complexidade de 
espaço). 
 Como já se discutiu para o tempo de execução, 
pode-se ter complexidade de melhor, médio e pior 
caso. 
 
 Em nosso estudo, a necessidade de espaço em 
memória será considerada constante e o termo 
complexidade designará complexidade de tempo 
de pior caso. 
 A expressão da complexidade de um algoritmo 
busca refletir suas condições intrínsecas, 
abstraindo aspectos ligados aos ambientes 
específicos de execução. 
 
 Assim, não são consideradas constantes de soma 
ou multiplicação. 
 
 Uma expressão como kn + c deve ser simplificada 
para n. 
 Outra condição que se assume é de que se está 
considerando o comportamento assintótico do 
algoritmo, ou seja: a complexidade expressa uma 
tendência a um limite à medida que cresce o 
tamanho do problema. 
 
 Supõe-se que a quantidade de dados a ser 
processada é suficientemente grande para essa 
tendência se evidenciar 
 Isto leva a outra simplificação: ao se ter uma 
expressão polinomial P(n), como os termos de 
menor grau podem ser desprezados (quando n é 
grande) diante do termo de maior grau, este é que 
será adotado como aproximação. 
 
 Exemplo: an³ + bn² - cn + d será reduzido a n³. 
 “A Complexidade de um Algoritmo 
consiste na 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.” 
 Existem três escalas de complexidade: 
◦ Melhor Caso 
◦ Caso Médio 
◦ Pior Caso 
 
 Nas três escalas, a função f(N) retorna a 
complexidade de um algoritmo com entrada 
de N elementos 
 Definido pela letra grega Ω (Ômega) 
 
 É o menor tempo de execução em uma entrada 
de tamanho N 
 
 É pouco usado, por ter aplicação em poucos 
casos. 
 
 Ex: Se tivermos uma lista de N números e quisermos encontrar 
algum deles assume-se que a complexidade no melhor caso é 
f(N) = Ω (1), pois assume-se que o número estaria logo na 
cabeça da lista. 
 
 
◦ Definido pela letra grega θ (Theta) 
◦ Dos três, é o mais difícil de se determinar. 
◦ Deve-se obter a média dos tempos de execução de todas as 
entradas de tamanho N, ou baseado em probabilidade de 
determinada condição ocorrer. 
◦ No exemplo anterior: 
 A complexidade média é P(1) + P(2) + ... + P(N) 
 Para calcular a complexidade média, basta conhecer as 
probabilidades de Pi; 
 Pi = 1/N, 1 <= i <= N 
 Isso resulta em P(1/N) + P(2/N) + ... + P(N/N) 
 Que resulta em 1/N(1+2+...+N) 
 Que resulta em 1 N(N+1) 
 N 2 
 Que resulta em f(N) = θ (N+1) 
 2 
 
Que Complicação!!! 
 Será o caso utilizado durante as aulas e é 
representado pela letra grega 
 
 O (O maiúsculo  ômicron maiúscula). 
 
 É o método mais fácil de se obter. Baseia-
se no maior tempo de execução sobre 
todas as entradas de tamanho N 
 
 Ex: Se tivermos uma lista de N números e quisermos 
encontrar algum deles, assume-se que a complexidade 
no pior caso é O (N), pois assume-se que o número 
estaria, no pior caso, no final da lista. 
 Exemplo: Busca seqüencial de um dado 
elemento em um vetor armazenando n 
elementos de forma aleatória. 
◦ Pior caso? 
◦ Melhor caso? 
◦ Caso médio? Supondo a distribuição uniforme e 
que o dado buscado está dentro do vetor. 
◦ Como muda o caso médio se o dado em geral 
não está presente? 
 Como exemplo, considere o número de 
operações de cada um dos dois algoritmos que 
resolvem o mesmo problema, como função de 
n. 
◦ Algoritmo 1: f1(n) = 2n² + 5n operações 
◦ Algoritmo 2: f2(n) = 500n + 4000 operações 
 
 Dependendo do valor de n, o Algoritmo 1 pode 
requerer mais ou menos operações que o 
Algoritmo 2. 
 (Compare as funções para n=10 e n=1000) 
◦ Algoritmo 1: f1(n) = 2n² + 5n operações 
◦ Algoritmo 2: f2(n) = 500n + 4000 operações 
 
 Um caso de particular interesse é quando n 
tem valor muito grande (n  ∞), 
denominado comportamento assintótico. 
 Os termos inferiores e as constantes 
multiplicativas contribuem pouco na 
comparação e podem ser descartados. 
◦ Algoritmo 1: f1(n) = 2n² + 5n operações 
◦ Algoritmo 2: f2(n) = 500n + 4000 operações 
 
 O importante é observar que f1(n) cresce 
com n² ao passo que f2(n) cresce com n. 
 Um crescimento quadrático é considerado 
pior que um crescimento linear. 
 Vamos preferir sendo assim o Algoritmo 2 
ao Algoritmo 1. Existem algoritmos com complexidade 
diversas. 
 
 Mas como saber qual é a complexidade de 
um determinado algoritmo implementado? 
 
 Para resolver esse problema, dividiu-se os 
algoritmos em “Classes de Problemas”, de 
acordo com o parâmetro que afeta o 
algoritmo de forma mais significativa 
1. Complexidade Constante 
 
2. Complexidade Linear 
 
3. Complexidade Logarítmica 
 
4. Complexidade n log n 
 
5. Complexidade Quadrática 
 
6. Complexidade Cúbica 
 
7. Complexidade Exponencial 
log n 
n 
n2 
2n 
n 
f 
n log n 
1 
(linear) 
(quadrática) 
(exponencial) 
(logarítmica) 
(constante) 
 São os algoritmos de complexidade O(1) 
 Independe do tamanho N de entradas 
 É o único em que as instruções dos 
algoritmos são executadas num tamanho 
fixo de vezes 
 Ex.: 
public void esvaziarVetor(int meuVetor[ ]){ 
 meuVetor = null; 
} 
 São os algoritmos de complexidade O(N) 
 Uma operação é realizada em cada elemento de 
entrada, ex.: pesquisa de elementos em uma lista 
public int imprimeVetor(int lista[ ]){ 
 for(int i=0; i < lista.length; i++){ 
 System.out.println(“valor: ”+lista[i]); 
 } 
} 
public int posicaoElemento(int lista[ ], int elemento){ 
 int posicao = -1; 
 boolean achou = false; 
 int tamanhoLista = lista.length; 
 int i = 0; 
 while(i < tamanhoLista && !achou){ 
 if (lista[i] == elemento){ 
 achou = true; 
 posicao = i; 
 } 
 i++; 
 } 
 return posicao; 
} 
O(N) 
O(1) 
O(1) 
O(1) 
O(1) 
O(1) 
O(1) 
O(1) 
f(N) = O(9 * O(1) + O(N)  O(O(1) + O(N))  O(N) 
 São os algoritmos de complexidade O(log n) 
 
 Ocorre tipicamente em algoritmos que 
dividem o problema em problemas menores 
 
 Ex.: O algoritmo de Busca Binária (estudados 
futuramente) 
 Como o próprio nome diz, são algoritmos 
que têm complexidade O(n log n) 
 
 Ocorre tipicamente em algoritmos que 
dividem o problema em problemas menores, 
porém juntando posteriormente a solução 
dos problemas menores 
A maioria dos algoritmos de ordenação externa são 
de complexidade logarítmica ou n log n 
 São os algoritmos de complexidade O(N²) 
 Itens são processados aos pares, geralmente 
com um loop dentro do outro 
public void somaMatriz (int matrizA[ ][ ], int matrizB[ ][ ]){ 
 for (int i=0; i < matrizA.length; i++){ 
 for (int j=0; j < matrizB.length; j++){ 
 matrizSoma[i,j] = matrizA[i][j] + matrizB[i][j]; 
 } 
 } 
} 
 São os algoritmos de complexidade O(N³) 
 Itens são processados três a três, geralmente 
com um loop dentro do outros dois. 
public void soma(int matrizSoma[ ][ ], int vetorB[ ]){ 
 int n = matrizSoma.length; 
 for (int i=0; i < n; i++){ 
 for (int j=0; j < n; j++){ 
 for (int k = 0; k < n; k++) 
 matrizSoma[i][j] = matrizSoma[i][j] + vetorB[k]; 
 } 
 } 
 } 
 São os algoritmos de complexidade O(2N) 
 
 Utilização de “Força Bruta” para resolvê-los 
(abordagem simples para resolver um 
determinado problema, geralmente baseada 
diretamente no enunciado do problema e nas 
definições dos conceitos envolvidos) 
 
 Geralmente não são úteis sob o ponto de 
vista prático 
 Exemplo de função exponencial: Fibonacci recursivo 
 Experimente rodar este algoritmo para: 
 n = 100. 
 
 A complexidade é O(2n). 
 
 Mesmo se uma operação levasse um 
picosegundo, 2100 operações levariam: 
 
 3x1013 anos = 30.000.000.000.000 anos!! 
 Faça a função de complexidade para 
os exercícios de vetores previamente 
passados em sala. 
 GOODRICH, Michael T; TAMASSIA, Robert. Estruturas de 
dados e algoritmos em JAVA. Porto Alegre: Bookman, 2002. 
 
 SZWARCFITER, Jayme Luiz; MARKENZON, Lílian. Estruturas de 
Dados e seus Algoritmos. Rio de Janeiro: LTC, 1994. 
 
 TOSCANI, Laira Vieira; VELOSO, Paulo A. S. Complexidade de 
Algoritmos. Porto Alegre: Sagra Luzzato, 2001. 
 
 TENENBAUM, Aaron M.; LANGSAM, Y. AUGENSTEIN, M. J. 
Estruturas de Dados Usando C. São Paulo: Makron Books, 
1995. 
 
 DEITEL, Harvey M.; DEITEL, Paul J. Java : como programar. 4. 
ed. Porto Alegre: Bookman, 2003.

Continue navegando