Vous êtes sur la page 1sur 57

INE5408

Estruturas de Dados

Complexidade de Algoritmos

- Complexidade de tempo
- Interpretao da complexidade de tempo
- Clculo da complexidade de tempo
Introduo
O estudo de Estruturas de Dados
basicamente o estudo de mtodos de
organizao de grandes quantidades
de dados. Estes mtodos incluem:
formas de organiz-los (estruturas);
tcnicas para manipul-los
(algoritmos bsicos).
Introduo
Pilhas, Listas e Filas so estruturas de dados tpicas;
para manipular estas estruturas - inserir elementos,
retirar elementos e ordenar elementos - necessitamos
de algoritmos;
estes algoritmos podem ser implementados de muitas
maneiras. Algumas simples e diretas, outras no to
simples - porm engenhosas - e outras ainda
complicadas e envolvendo muitas operaes;
quando trabalhamos com quantidades muito grandes
de dados, um projeto ruim de algoritmo para
manipular uma estrutura de dados pode resultar em
um programa que apresenta um tempo de execuo
invivel.
Introduo
Quando estudamos algoritmos, um
aspecto que devemos considerar, alm
de sua correo, a anlise da sua
eficincia.
A anlise de algoritmos pode ser
definida como o estudo da estimativa
do tempo de execuo dos
algoritmos (M. A. Weiss).
Idias bsicas
Um algoritmo um conjunto finito de
passos que devem ser seguidos com
um conjunto de dados de entrada para
se chegar soluo de um problema;
um problema, geralmente, pode ser
resolvido por muitos algoritmos
diferentes;
exemplo: clculo da potncia xn de um
nmero inteiro x.
Idias bsicas
//Verso iterativa.
inteiro potncia(x, n)
inteiro y, i;
incio
i <- n;
y <- 1;
enquanto (i > 0) faa
y <- y * x;
i <- i - 1;
fim enquanto
retorne y;
fim
Idias bsicas
//Verso recursiva.
inteiro potncia_recursiva(x, n)
inteiro y;
incio
se (n = 1) ento
retorne x;
y <- potncia_recursiva (x, (n / 2));
se (mpar(n)) ento
retorne x*y*y;
seno
retorne y*y;
fim se
fim
Idias bsicas
O fato de existir um algoritmo para
resolver um problema no implica
necessariamente que este problema
possa realmente ser resolvido na
prtica. H restries de tempo e de
espao de memria.
Exemplo: calcular todas as possveis
partidas de xadrez.
Idias bsicas
Um algoritmo uma idia abstrata de como
resolver um determinado problema. Ele , a
princpio, independente da mquina que o
executar e de suas caractersticas.
Um programa uma implementao de um
algoritmo em uma linguagem particular que
ser executado em um computador particular.
Um programa est sujeito s limitaes fsicas
da mquina onde ser executado, como
capacidade de memria, velocidade do
processador e dos perifricos, entre outras.
Idias bsicas
O tempo que a execuo de um programa toma
uma grandeza fsica que depende:
do tempo que a mquina leva para executar
uma instruo ou um passo de programa;
da natureza do algoritmo, isto , de quantos
passos so necessrios para se resolver o
problema para um dado;
do tamanho do conjunto de dados que
constitui o problema.
Problema bsico na Anlise de Algoritmos
Necessitamos definir uma forma de criar
uma medida de comparao entre
diferentes algoritmos que resolvem um
mesmo problema, para:
podermos saber se so viveis;
podermos saber qual o melhor algoritmo
para a soluo do problema.
Problema bsico na Anlise de Algoritmos
Para fazermos isso, abstramos de um
computador em particular e
assumimos que a execuo de todo e
qualquer passo de um algoritmo leva
um tempo fixo e igual a uma unidade de
tempo:
o tempo de execuo em um computador
particular no interessante;
muito mais interessante uma comparao
relativa entre algoritmos.
Problema bsico na Anlise de Algoritmos
Modelo de computao
as operaes so todas executadas
seqencialmente;
a execuo de toda e qualquer operao
toma uma unidade de tempo;
a memria do computador infinita.
Assim nos sobram duas grandezas:
tempo = nmero de operaes executadas;
quantidade de dados de entrada.
Complexidade de Tempo
Podemos expressar de forma abstrata a
eficincia de um algoritmo descrevendo
o seu tempo de execuo como uma
funo do tamanho do problema
(quantidade de dados). Isto chamado
de complexidade de tempo.
Exemplo: ordenao de um Vetor.
Primeiro caso: Bubblesort
Bubblesort o mais primitivo dos mtodos
de ordenao de um vetor. A idia
percorrer um vetor de n posies n
vezes, a cada vez comparando dois
elementos e trocando-os caso o
primeiro seja maior que o segundo.
Primeiro caso: Bubblesort
//Mtodo da bolha.
Bubblesort(a[], n)
inteiro i, j, x;
incio
para i de 1 at n faa
para j de 2 at n faa
se (a[j-1] > a[j]) ento
x <- a[j-1];
a[j-1] <- a[j];
a[j] <- x;
fim se
fim para
fim para
fim
Primeiro caso: Bubblesort
A comparao (a[j-1] > a[j]) vai ser
executada n*(n-1) vezes. No caso de
um vetor na ordem inversa, as
operaes da atribuio triangular
podero ser executadas at 3*n*(n-1)
vezes, j que uma troca de elementos
no significa que um dos elementos
trocados tenha encontrado o seu lugar
definitivo.
Segundo caso: StraightSelection
O mtodo da seleo direta uma forma
intuitiva de ordenarmos um vetor:
escolhemos o menor elemento do vetor
e o trocamos de posio com o primeiro
elemento.
Depois comeamos do segundo e
escolhemos novamente o menor dentre
os restantes e o trocamos de posio
com o segundo e assim por diante.
Segundo caso: StraightSelection
StraightSelection(a[], n)
inteiro i, j, k, x;
incio
para i de 1 at n-1 faa
k <- i;
x <- a[i];
para j de i+1 at n faa
se (a[j] < x) ento
k <- j;
x <- a[k];
fim se
fim para
a[k] <- a[i];
a[i] <- x;
fim para
fim
Segundo caso: StraightSelection
Neste algoritmo o nmero de vezes que a
comparao (a[j] < x) executada
expresso por (n-1)+(n-2)+...+2+1 =
(n/2)*(n-1).
O nmero de trocas a[k] <- a[i]; a[i] <- x
realizado no pior caso, onde o vetor
est ordenado em ordem inversa,
somente n-1 vezes, num total de 2*(n-
1).
Interpretao
Como j foi dito, a nica forma de se
poder comparar dois algoritmos
descrevendo o seu comportamento
temporal em funo do tamanho do
conjunto de dados de entrada. Assim:
Talgoritmo = f(n), onde n o tamanho
do conjunto de dados.
Interpretao
Se tomarmos as operaes de troca de
valores como critrio-base, podemos
dizer que:

TBubblesort = 3*n*(n-1) sempre


TStraightSelection = 2*(n-1) para o pior caso
Interpretao
O que nos interessa o comportamento
assinttico de f(n), ou seja, como f(n)
varia com a variao de n.
Razo: para mim interessante saber
como o algoritmo se comporta com uma
quantidade de dados realstica para o
meu problema e o que acontece quando
eu vario esses dados.
Interpretao
Exemplo: eu tenho dois algoritmos (a e b)
para a soluo de um problema. Se a
complexidade de um expressa por
fa(n) = n2 e a do outro por fb(n) = 100*n,
significa que o algoritmo a cresce
quadraticamente (uma parbola) e que
o algoritmo b cresce linearmente
(embora seja uma reta bem inclinada).
Interpretao
Se eu uso estes algoritmos para um
conjunto de 30 dados, o segundo com
Tb=3.000 pior do que o primeiro com
Ta=900.
Se eu os uso para um conjunto de 30.000
dados, porm, terei Ta=900.000.000 e
Tb=3.000.000.
Isto ocorre porque o comportamento
assinttico dos dois bem diferente.
Interpretao
Interpretao da Complexidade de Tempo
Aspecto essencial que deve ser expresso
pelo clculo de complexidade:
Qual o comportamento assinttico
predominante de um algoritmo
em funo do tamanho do
conjunto de dados a ser processado.
Exemplo: se linear, polinomial
(quadrtico, cbico, etc.), logartmico ou
exponencial.
Anlise Assinttica
Para a anlise do comportamento de
algoritmos existe toda uma terminologia
prpria.
Para o clculo do comportamento de
algoritmos foram desenvolvidas
diferentes medidas de complexidade.
A mais importante delas e que usada na
prtica chamada de Ordem de
Complexidade ou Notao-O ou Big-
Oh.
Anlise Assinttica
Definio (Big-Oh): T(n) = O(f(n)) se existem
constantes c e n0 tais que T(n)c.f(n) quando nn0.
A definio indica que existe uma constante c que
faz com que c.f(n) seja sempre pelo menos to
grande quanto T(n), desde que n seja maior que
um n0.
Em outras palavras: a Notao-O me fornece a
Ordem de Complexidade ou a Taxa de
Crescimento de uma funo.
Para isso, no consideramos os termos de ordem
inferior da complexidade de um algoritmo,
apenas o termo predominante.
Anlise Assinttica
Exemplo: algoritmo com complexidade T(n) =
3n2 + 100n.
Nesta funo, o segundo termo tem um peso
relativamente grande, mas a partir de n0 = 11,
o termo n2 que "d o tom" do crescimento
da funo: uma parbola. A constante 3
tambm tem uma influncia irrelevante sobre
a taxa de crescimento da funo aps um
certo tempo.
Por isso dizemos que este algoritmo da ordem
de n2 ou que tem complexidade O(n2).
Anlise Assinttica
Funo Nome
1 Constante
log n Logartmica
log2 n Log-quadrtica
n Linear
n log n n log n
n2 Quadrtica
n3 Cbica
2n Exponencial
Diferentes Tempos de Execuo
Problema da Subseqncia de Soma Mxima: dada
uma seqncia de nmeros a1, a2, ... , an, positivos ou
negativos, encontre uma subseqncia aj, ..., ak
dentro desta seqncia cuja soma seja mxima. A
soma de uma seqncia contendo s nmeros
negativos por definio 0.
Exemplo: para a seqncia -2, 11, -4, 13, -5, -2, a
resposta 20 (a2,a3,a4).
Este problema oferece um bom exemplo para o estudo
de como diferentes algoritmos que resolvem o
mesmo problema possuem diferentes
comportamentos, pois para ele existem muitas
solues diferentes.
Diferentes Tempos de Execuo
Algoritmo 1 2 3 4
Tempo O(n3) O(n2) O(n log n) O(n)
n = 10 0,00103 0,00045 0,00066 0,00034
n = 100 0,47015 0,01112 0,00486 0,00063
n = 1.000 448,77 1,1233 0,05843 0,00333
n = 10.000 NA 111,13 0,68631 0,03042
n = 100.000 NA NA 8,0113 0,29832
Clculo da Complexidade de Tempo
Um exemplo intuitivo

inteiro somaCubos(inteiro n)
inteiro i, somaParcial;
incio
1 somaParcial <- 0;
2 para i de 1 at n faa
3 somaParcial <- somaParcial + i * i * i;
4 fim para
5 retorne somaParcial;
fim
Clculo da Complexidade de Tempo
Anlise:
as declaraes no tomam tempo nenhum;
a linha 4 tambm no toma tempo nenhum;
as linhas 1 e 5 contam uma unidade de tempo cada;
a linha 3 conta 4 unidades de tempo (2 multiplicaes,
uma adio e uma atribuio) e executada n vezes,
contando com um total de 4n unidades de tempo;
a linha 2 possui custos implcitos de inicializar i, testar
se menor que n e increment-lo. Contamos 1 unidade
para sua inicializao, n + 1 para todos os testes e n
para todos os incrementos, o que perfaz 2n + 2
unidades de tempo;
o total perfaz 6n + 4 unidades de tempo, o que indica
que o algoritmo O(n), da Ordem de Complexidade n,
ou seja, linear.
Regras para o clculo
Laos: o tempo de execuo de um lao , no mximo, a
soma dos tempos de execuo de todas as instrues
dentro do lao (incluindo todos os testes) multiplicado pelo
nmero de iteraes.

Laos aninhados: analise-os de dentro para fora. O tempo


total de execuo de uma instruo dentro de um grupo
de laos aninhados o tempo de execuo da instruo
multiplicado pelo produto dos tamanhos de todos os laos.

Exemplo: O(n2)
para i de 1 at n faa
para j de 1 at n faa
k <- k + 1;
fim para
fim para
Regras para o clculo
Instrues Consecutivas: estes simplesmente somam, sendo os
termos de ordem menor da soma ignorados.

Exemplo: O(n) + O(n2) = O(n2)


para i de 1 at n faa
a[i] <- 0;
fim para
para i de 1 at n faa
para j de 1 at n faa
a[i] <- a[j] + k + 1;
fim para
fim para
Regras para o clculo
Se / Ento / Seno: considere o fragmento de cdigo abaixo.

se cond ento
expressso1
seno
expresso2
fim se

O tempo de execuo de um comando Se / Ento / Seno


nunca maior do que o tempo de execuo do teste cond
em si mais o tempo de execuo da maior dentre as
expresses expresso1 e expresso2. Ou seja: se
expresso1 O(n3) e expresso2 O(n), ento o teste
O(n3) + 1 = O(n3).
Regras para o clculo
Chamada a Funes: segue a mesma
regra dos laos aninhados - analise tudo
de dentro para fora. Ou seja: para
calcular a complexidade de um
programa com vrias funes, calcula-
se primeiro a complexidade de cada
uma das funes e depois considera-se
cada uma das funes como uma
instruo com a complexidade de
funo.
Regras para o clculo
Recurso: a parte mais difcil da anlise de
complexidade. Na verdade existem dois casos:
muitos algoritmos recursivos mais simples podem
ser "linearizados", substituindo-se a chamada
recursiva por alguns laos aninhados ou por uma
outra subrotina extra e eventualmente uma pilha
para control-la. Nestes casos, o clculo simples
e pode ser feito depois da "linearizao". Em
muitos algoritmos recursivos, porm, isto no
possvel. Nestes casos obtemos uma relao de
recorrncia que tem de ser resolvida e uma tarefa
matemtica menos trivial.
Regras para o clculo
Exemplo de clculo de complexidade
em recurso: Fatorial
inteiro Fatorial(inteiro n)
incio
se n <= 1 ento
retorne 1
seno
retorne (n * Fatorial (n - 1));
fim se
fim
Regras para o clculo
O exemplo anterior realmente um exemplo pobre de recurso e
pode ser "iterativisado" de forma extremamente simples com
apenas um lao para-faa:

inteiro FatorialIterativo(inteiro n)
inteiro i, fatorial;
incio
fatorial <- 1;
para i de 2 at n faa
fatorial <- fatorial * i;
fim para
retorne fatorial;
fim

A complexidade de FatorialIterativo pode ento ser facilmente


calculada e evidente que O(n).
Regras para o clculo
O caso dos nmeros de Fibonacci abaixo no to simples e
requer a resoluo de uma relao de recorrncia:

inteiro Fibonacci(inteiro n)
incio
se n <= 1 ento
retorne 1
seno
retorne (Fibonacci(n-1) + Fibonacci(n-2));
fim se
fim

Observando o algoritmo, vemos que para n >= 2 temos um tempo


de execuo T(n) = T(n-1)+T(n-2)+2. A resoluo desta relao
nos mostra que Fibonacci O(()n).
Logaritmos e outros Tempos de Execuo
O aspecto mais complexo na anlise de
complexidade centra-se em torno do
logaritmo. Para analisar-se um algoritmo de
complexidade logartmica e chegar-se a um
resultado correto sobre a sua ordem exata de
complexidade necessria uma certa
experincia e algum "jeito" matemtico.
Algumas regras de aproximao podem ser
dadas: algoritmos seguindo a tcnica Dividir-
Para-Conquistar so muitas vezes n log n.
Logaritmos e outros Tempos de Execuo
Quando um algoritmo, em uma passada de
uma iterao toma o conjunto de dados e o
divide em duas ou mais partes, sendo cada
uma dessas partes processada separada e
recursivamente, este algoritmo utiliza a
tcnica dividir-para-conquistar e ser
possivelmente n log n;
um algoritmo log n se ele toma um tempo
constante O(1) para dividir o tamanho do
problema, usualmente pela metade;
a pesquisa binria um exemplo de log n.
Logaritmos e outros Tempos de Execuo
Se o algoritmo toma tempo constante
para reduzir o tamanho do problema em
um tamanho constante, ele ser O(n).
Algoritmos combinatrios so
exponenciais: se um algoritmo testa
todas as combinaes de alguma coisa,
ele ser exponencial.
Exemplo: Problema do Caixeiro Viajante
Checando a sua anlise
Uma vez que a anlise de complexidade tenha
sido executada, interessante verificar-se se
a resposta est correta e to boa quanto
possvel.
Uma forma de se fazer isto o procedimento
pouco matemtico de se codificar o trecho de
algoritmo cuja complexidade se tentou
descrever e verificar se o tempo de execuo
coincide com o tempo previsto pela anlise.
Quando n dobra, o tempo de execuo se eleva
de um fator 2 para algoritmos lineares, fator 4
para quadrticos e fator 8 para cbicos.
Checando a sua anlise
Programas logartmicos s aumentam o seu
tempo de execuo de uma constante a cada
vez que n dobra. Algoritmos de O(n log n)
tomam um pouco mais do que o dobro do
tempo sob as mesmas circunstncias.
Estes aumentos podem ser difceis de se
detectar se os termos de ordem inferior tm
coeficientes relativamente grandes e n no
grande o suficiente. Um exemplo o pulo no
tempo de execuo de n=10 para n=100 em
algumas implementaes do problema da
subseqncia de soma mxima.
Checando a sua anlise
Distinguir programas n log n de
programas lineares s em evidncia de
tempo de execuo pode tambm ser
muito difcil.
Uma boa praxe , caso o programa no
seja exponencial (o que voc vai
descobrir muito rpido), fazer alguns
experimentos com conjuntos maiores de
dados de entrada.
Exerccio: clculo de complexidade
1. Floyd
Considere o grafo e sua matriz de custos
D, abaixo:
Exerccio: clculo de complexidade
Pelo algoritmo de Floyd pode-se obter a Matriz de
Custos A com os comprimentos dos menores
caminhos e a Matriz de Roteamento R.
Exemplo: custo e rota v4 -> v3
v3

v1->v3

v2->v3

v4 3 v4->v3

v4->v3 = v4->v1->v3->v2
Exerccio: clculo de complexidade
Agora, por exemplo, para determinar a
rota de v2 para v1, toma-se R[2,1] = v5,
R[5,1] = v4, R[4,1] = v1.
Logo, a rota de v2 para v1 :

v2 v5 v4 v1
Exerccio: clculo de complexidade
Algoritmo de Floyd modificado
Considere a matriz de custos D[n,n]
definida como no algoritmo de
Floyd. O algoritmo produzir uma
matriz A[n,n], com comprimentos
dos menores caminhos e ainda
uma matriz R[n,n] que fornece o
vrtice k, que o primeiro vrtice a
ser visitado no menor caminho de vi
at vj.
Exerccio: clculo de complexidade
FloydModificado()
incio
para i = 1 at n faa
para j = 1 at n faa
A[i,j] <- D[i,j];
R[i,j] <- 0;
fim para
fim para
para i = 1 at n faa
A[i,i] <- 0;
fim para
para k = 1 at n faa
para i = 1 at n faa
para j = 1 at n faa
se A[i,k] + A[k,j] < A[i,j] ento
A[i,j] <- A[i,k] + A[k,j];
R[i,j] <- k;
fim para
fim para
fim para
fim
Exerccio: clculo de complexidade
2. Torres de Hanoi
2.1. Considere o Problema das Torres de Hanoi com 3
Pinos na sua verso iterativa, como visto em aula:
um programa que itera sempre sobre duas jogadas: a
menor pea e outra possvel de ser movida
Voc viu que para 2 discos, houve 3 movimentaes de
disco e para 3 discos o algoritmo executou 7
movimentaes.
Qual essa tendncia ? Ser que esse comportamento
continuar seguindo essa tendncia?
Calcule a complexidade do algoritmo das torres de Hanoi
Exerccio: clculo de complexidade
2. Torres de Hanoi
2.2. Considere o Problema das Torres de Hanoi
implementado por voc em aula:
Mantendo o nmero de pilhas (pinos) constante, voc pode
escolher um nmero arbitrrio de discos.
Modifique o programa para poder mensurar o tempo de
execuo.
Use as funes ftime(), ctime(), difftime().
Observe que difftime() s tem sentido se o programa rodar mais
de um segundo, o que no acontecer para valores baixos.
Rode o programa para 2, 3, 6, 7,10, 30, 50, 100, 200, 300,
500, 1000, 2000, 10.000, 50.000,100.000 e 500.000 discos.
Exerccio: clculo de complexidade
2. Torres de Hanoi
Ao final o programa
dever chamar o
programa unix gnuplot
com o arquivo de
tempos como
parmetro para que
um grfico dos tempos
seja mostrado na tela.
Para tanto esse
arquivo dever ser
gerado na sintaxe do
gnuplot, detalhada no
manual do gnuplot.

Vous aimerez peut-être aussi