Anlise de Algoritmos
PROF. MAURCIO DUARTE
UNIVEM
Introduo
Sabemos que um algoritmo um conjunto de passos para se
chegar com sucesso a um objetivo;
Para conhecermos um algoritmo, podemos analis-lo, ou seja,
estudar suas especificaes tais como:
o tempo de processamento de um programa como funo
de seus dados de entrada;
quantidade de memria total requerida para os dados do
programa;
comprimento total do cdigo do programa;
se o programa chega corretamente ao resultado desejado;
a complexidade do programa, se fcil de ler, entender e
modificar;
robustez do programa, ou seja, como ele lida com
entradas errneas ou inesperadas.
Introduo
O comportamento de um algoritmo
influencia o seu desempenho;
Basicamente existem dois tipos de
problemas distintos na anlise de algoritmos:
Introduo
Maneiras de avaliar o custo computacional de
um algoritmo:
executar o programa em um computador real e medir o
tempo de execuo (Emprica);
atravs de um modelo matemtico (Terica ou
Analtica);
Avaliao Emprica
Implementa-se o algoritmo em um computador e medese o seu tempo de execuo para a resoluo de
algumas instncias do problema.
Assim, pode-se determinar o pior, o caso mdio e o
melhor caso para o volume de dados testado
Entretanto, o tempo gasto vai depender:
Avaliao Terica ou
Analtica
Consiste em encontrar uma frmula
matemtica que expresse o recurso (por
exemplo, o tempo ou o nmero de operaes
executadas) necessrio para o algoritmo
executar em funo do tamanho dos dados
de entrada.
Esta frmula retrata a ordem de
crescimento do tempo de execuo do
algoritmo em funo do tamanho da entrada
Funo de complexidade de
um algoritmo
Uma funo de complexidade f utilizada para
medir o custo de execuo de um algoritmo;
f(n) uma funo de custo para executar um
algoritmo de tamanho n;
As funes de complexidade podem ser:
Exemplo 1
int maior( int *vet, int n )
{
int j, aux = vet[0];
for( j = 1; j < n; j++ )
if( vet[j] > aux )
aux = vet[j];
return aux;
}
Funo de complexidade de
um algoritmo
Em anlise de algoritmos destacamos trs
situaes bsicas para determinar a
complexidade: melhor caso, pior caso e o
caso mdio ou esperado;
O melhor caso corresponde ao menor tempo de
execuo sobre todas a entradas possveis de
tamanho n;
O pior caso corresponde ao maior tempo de execuo;
O caso mdio mdia dos tempos de execuo de
todas as entradas de tamanho n;
Exemplo 2
Considere como exemplo a localizao de um
registro em um arquivo. Se f a funo de
complexidade de forma que f(n) representa o
nmero de registros consultados no arquivo,
temos os seguintes casos a considerar:
Melhor caso: f(n) = 1
Pior caso: f(n) = n
Caso mdio: f(n) = (n+1)/2
Exemplo 3
Considere o seguinte trecho de
algoritmo:
n = 1;
while( n <= 1000 )
{
(instrues);
n = n + 1;
}
Qual a funo de
complexidade?
Exemplo 4
Considere o seguinte trecho
de algoritmo:
n = 1;
while( n <= 1000 )
{
(instrues);
n = n + 2;
}
Qual a funo de
complexidade?
Exemplo 5
Considere o trecho de
algoritmo:
Considere o trecho de
algoritmo:
n = 1;
n = 1000;
while( n >= 1 )
(instrues);
(instrues);
n = n * 2;
n = n / 2;
Exemplo 6
Considere o trecho de algoritmo
abaixo:
n = 1;
while( n <= 10 )
{
k = 1;
while( k <= 10 )
{
(instrues);
k = k * 2;
}
n = n + 1;
}
Exemplo 7
Considere o trecho de algoritmo:
n = 1;
while( n <= 10 )
{
k = 1;
while( k <= 10 )
{
(instrues);
k = k + 1;
}
n = n + 1;
}
Qual a funo de
complexidade?
Exerccio
1.) Para o algoritmo abaixo, escreva a funo de complexidade.
Inicio
inteiro a, b, c=0;
leia (%d, &a);
para (b=1; b<=a; b++)
inicio
c += b;
escreva(%d , b);
fim
escreva(%d, c);
fim
Exerccio
2.) Para o algoritmo abaixo, escreva a funo de complexidade.
Inicio
inteiro a[10][10], i, j, soma=0;
para(i=0; i<10; i++)
para(j = 0; j<10; j++)
inicio
leia (%d, &a[i][j]);
soma += a[i][j];
fim
escreva(%d, soma);
fim
Notao O (micron
Big O)
Em 1968 foi sugerida uma notao para
caracterizar a complexidade de um
algoritmo. Essa inveno ficou conhecida
como notao O;
Para representarmos uma expresso
(composta por vrios termos) em notao
O, devemos levar em considerao a
parte que cresce mais rpido em funo
do argumento da funo. As constantes
so desprezadas na representao;
Comportamento
assinttico de funes
Parmetro n fornece uma medida da
dificuldade para resolver um problema;
Para valores pequenos de n qualquer
algoritmo custa pouco para ser executado;
A anlise de algoritmos leva em
considerao valores grandes de n;
Comportamento assinttico de uma
funo de custo o limite do
comportamento do custo quando n cresce;
Comportamento
assinttico de funes
Relata o crescimento assinttico das operaes consideradas
na anlise de algoritmos;
Uma funo f(n) domina assintoticamente outra funo
g(n) se existem duas constantes positivas c e m tais que,
para n m, tem-se que |g(n)| c|f(n)|.
Notao O
Notao utilizada para representar a dominao assinttica;
Para dizer que uma funo f(n) domina assintoticamente
uma funo g(n) pode-se escrever: g(n) = O(f(n));
A expresso deve ser lida: g(n) da ordem no mximo f(n);
Dizer que o tempo de execuo y(n) de um algoritmo
O(n2) significa que existem constantes c e m tais que, para
valores de n m, |y(n)| c|n2|;
Exemplos
Seja g(n) = n+10 e f(n) = n2
A pergunta : g(n) O(f(n2))? Ou seja, f(n) domina
assintticamente g(n)?
A resoluo consiste em
Intuitivamente pode-se perceber que uma equao
quadrtica e a outra linear
Assim, sabemos (intuitivamente) que a quadrtica domina a
linear.
Entretanto, precisamos encontrar m e a constante c
Exemplos
Uma das formas de resolver atribuir valores s duas funes
e averiguar o comportamento delas
(n+10)
1
2
3
4
5
11
12
13
14
15
n2
1
4
9
16
25
Exemplos
g(n)*1000
f(n2)
100
110000
10000
150
160000
22500
200
210000
40000
250
260000
62500
300
310000
90000
350
360000
122500
400
410000
160000
450
460000
202500
500
510000
250000
550
560000
302500
600
610000
360000
650
660000
422500
700
710000
490000
750
760000
562500
800
810000
640000
850
860000
722500
900
910000
810000
950
960000
902500
1000
1010000
1000000
1050
1060000
1102500
1100
1110000
1210000
1150
1160000
1322500
1200
1210000
1440000
1250
1260000
1562500
1300
1310000
1690000
Exemplos de expresses em
notao O
G(n) = n2 + 2n + 1 = O(n2)
G(n) = 3n3 + 2n2 + n = O(n3)
H(n) = n2 + nlogn + n = O(n2)
X(n) = 3n3 = O(n3)
Observao: As funes de complexidade
de tempo so definidas sobre os inteiros no
negativos, ainda que possam ser no
inteiros.
Nome
O(1)
Constante
O(log n)
Logartmica
O(n)
Linear
O(n log n)
Linear logartmica
O(n2)
Quadrtica
O(n3)
Cbica
O(2n)
Exponencial
Principais funes de
complexidade
1. f(n) = O(1): O seu uso independe do valor n;
2. f(n) = O(log n): este tipo de execuo ocorre
tipicamente em algoritmos que resolvem um
problema transformando-o em problemas
menores;
3. f(n) = O(n): em geral, um pequeno trabalho
realizado sobre cada elemento de entrada;
4. f(n) = O(n2): ocorre tipicamente em algoritmos
que processam os dados de entrada em pares,
muitas vezes um lao dentro do outro;
Principais funes de
complexidade
5.
Exemplo de crescimento
das funes
n
log2n
n log2n
n2
n3
2n
10
3,32
33
100
1000
1024
100
6,64
664
10.000
1.000.000 1,26x1030
1000
9,97
9970
1.000.000
109
1,07x10301
Tcnicas de Anlise de
Algoritmos
Infelizmente no existe um conjunto de regras
para analisar um programa. Segue alguns
princpios:
O tempo de execuo de um comando de atribuio,
leitura ou de escrita pode ser considerado como O(1);
O tempo de execuo de uma seqncia de comandos
determinado pelo maior tempo de execuo de qualquer
comando da seqncia;
Tcnicas de Anlise de
Algoritmos
O tempo de execuo de um comando de deciso
composto pelo tempo de execuo dos comandos
executados dentro do comando condicional, mais o tempo
para avaliar a condio, que O(1);
O tempo para executar um lao a soma do tempo de
execuo do corpo do lao mais o tempo de avaliar a
condio de trmino, que O(1); multiplicado pelo
nmero de iteraes do lao;
Tcnicas de Anlise de
Algoritmos
Para programas que apresentam procedimentos no
recursivos, o tempo de execuo calculado separadamente
para cada procedimento. O clculo deve iniciar pelos
procedimentos que no chamam outros procedimentos;
Para programas com procedimentos recursivos, para cada
procedimento associado uma funo de complexidade;
Operaes com a
notao O
1.
f(n) = O(f(n))
2.
3.
4.
O(O(f(n))) = O(f(n))
5.
6.
7.
Exemplo 8
Determine a complexidade da funo abaixo:
void f( int a[], int n )
{
int i, j, min, x;
for( i = 0; i <= n 1; i++ )
{
min = i;
for( j = i+1; j <= n; j++ )
if( a[j] < a[min] )
min = j;
x = a[min]; a[min] = a[i]; a[i] = x;
}
}
Soluo...
O primeiro for executado n vezes e o for mais interno
(no pior caso), n-1 vezes. Ento, tem-se:
Pior caso n.(n-1) = n2 - n
Portanto, O (n2)
Complexidade em
procedimentos recursivos
Se existirem procedimentos recursivos em
um algoritmo, o problema deve ser tratado
de forma diferente;
Para cada procedimento recursivo
associada uma funo de complexidade
(f(n)) desconhecida, onde n mede o tamanho
dos argumentos para o procedimento;
Em seguida obtida uma equao de
recorrncia, ou seja, uma expresso
envolvendo a mesma funo;
Exemplo 9
Determine a complexidade do procedimento abaixo:
void pesquisa( int n )
{
if( n <= 1 )
//inspecione elemento e termine
else
for( int i = 1; i <= n; i++ )
{
//inspecione cada um dos elementos
pesquisa( n/3 );
}
}