7. Introdução à Complexidade de Algoritmos Análise de Algoritmos

Propaganda
7. Introdução à Complexidade de Algoritmos
Fernando Silva
DCC-FCUP
Estruturas de Dados
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
1/1
Análise de Algoritmos
No desenvolvimento de algoritmos é importante ter a noção da eficiência
de um algoritmo, i.e. da eficiência que pode ter uma implementação do
algoritmo.
Eficiência normalmente mede-se em tempo de execução ou espaço
(memória) necessário à execução do algoritmo (ou programa
associado).
Tempo de Execução de um algoritmo varia com o input e
normalmente aumenta com o tamanho do input.
I
I
caso médio é difícil de determinar.
normalmente, olha-se para o pior caso possível de tempo de execução:
F
F
mais simples de analizar
crucial nas aplicações mais exigentes, jogos, etc.
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
2/1
Como aferir a eficiência
Como aferir a eficiência, por exemplo, o tempo de execução?
Análise empírica – executando o programa com inputs de tamanho e
composição variados, mas
I
I
I
nem sempre é simples concretizar o algoritmo, ou
os resultados podem não ser conclusivos,
comparação de algoritmos obriga a usar igual software e hardware.
Análise teórica
I
I
I
I
usa uma descrição de mais alto nível do algoritmo em vez da
implementação,
caracteriza o tempo de execução como uma função do tamanho do
input, n,
tem em conta todos os possíveis inputs,
permite avaliar eficiência de forma independente do ambiente de
hardware/software.
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
3/1
Exemplo de análise de complexidade - findMax()
Como calcular o tempo de execução do algoritmo seguinte:
Pressupostos (RAM -Random Access Memory):
memória ilimitada e endereços contêm um no arbitrário ou caracteres,
aceder ao conteúdo de um endereço custa uma unidade de tempo.
max= A[0]; → 1 leitura de A[0] + 1 atribuição a max.
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
4/1
Determinar complexidade do findMax()
Casos possíveis:
caso mais favorável (A[0] é o maior elemento):
t(n) = 2 + 1 + n + 4(n − 1) + 1 = 5n operações primitivas
pior caso:
t(n) = 2 + 1 + n + 6(n − 1) + 1 = 7n − 2
caso médio? difícil de calcular, depende da distribuição do input; usar
teoria de probabilidades.
Normalmente, olharemos para o pior caso, pois dá-nos um limite superior
do tempo de execução.
Cálculo do tempo de execução:
seja a o tempo observado para a operação primitiva mais rápida
seja b o tempo observado para a operação primitiva mais lenta
então, o pior tempo de execução T (n) será
a(7n − 2) ≤ T (n) ≤ b(7n − 2) ⇒ T (n) limitado por 2 funções lineares
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
5/1
Taxa de crescimento do tempo de execução
Saliente-se que:
o tempo de execução, T (n), pode ser afectado pela alteração do
ambiente hardware/software, mas
tal não acontece se considerarmos a taxa de crescimento de T (n)
A taxa de crescimento de T (n) corresponde
ao crescimento de T (n) quando se aumenta o valor de n.
O exemplo findMax()
mostrava T (n) limitado por 2 funções lineares em n, significando que
o tempo de execução varia na mesma proporção que n.
Logo, diz-se que o crescimento de T (n) é linear.
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
6/1
Taxas de crescimento (1)
logarítmica
linear
quadrática
cúbica
polinomial
exponencial
≈ log2 n
≈n
≈ n2
≈ n3
≈ nk
≈ an (a > 1)
Crescimento de
n log2 n
2
1
8
3
16
4
...
...
1024
10
algumas funções:
√
n
n n log2 n
1.4
2
2
2.8
8
24
4.0
16
64
...
...
...
32 1024
10240
Fernando Silva (DCC-FCUP)
n2
4
64
256
...
> 106
n3
8
512
4096
...
> 109
7. Introdução à Complexidade de Algoritmos
2n
4
256
65536
...
> 10308
Estruturas de Dados
7/1
Taxas de crescimento (2)
Se assumirmos que cada operação pode ser executada em 1µs (micro-sec),
qual será o maior problema (função de n) para um programa que execute
em 1 seg., 1 min., 1 hora?
T (n)
400n
20ndlog ne
2n2
n4
2n
Tamanho máximo problema (n)
1 seg.
1 min.
1 hora
2500 150,000
9,000,000
4096 166,666
7,826,087
707
5,477
42,426
31
88
244
19
25
31
No caso de crescimento exponencial, apenas conseguimos tratar problemas
para dimensões muito pequenas de n.
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
8/1
A definição “big-Oh” O()
Definição de ordem de complexidade assimptótica:
Sejam f (n) e g(n) funções de N0 7−→ R.
f (n) é O(g(n)) (ou seja, f (n) é da ordem de g(n))
se ∃c > 0, ∃n0 ≥ 1 : f (n) ≤ cg(n), ∀n ≥ n0
Interpretação gráfica:
O(g(n)) corresponde ao limite
superior da taxa de crescimento de
f (n).
dizer que f (n) é O(g(n)), significa
dizer que f (n) não cresce mais do que
g(n).
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
9/1
Exemplos - O()
2n + 10 é O(n)
porque:
2n + 10 ≤ cn
⇒
(c − 2)n ≥ 10
⇒
n≥
para c = 3 e n0 = 10 verifica-se sempre que 2n + 10 ≤ cn
10
(c − 2)
outras funções:
20n3 + 10n log n + 5
ak nk + ak−1 nk−1 + . . . + a0
3 log n + log log n
2100
5
n
Fernando Silva (DCC-FCUP)
—
—
—
—
—
7. Introdução à Complexidade de Algoritmos
O(n3 )
O(nk )
O(log n)
O(1)
O( n1 )
Estruturas de Dados
10 / 1
Regras de simplificação
Algumas regras que olhando para expressões mais complexas,
permitem-nos fazer simplificações:
Se d(n) ∼ O(f (n)), então ad(n) (com a > 0) ∼ O(f (n))
Se d(n) ∼ O(f (n)) e e(n) ∼ O(g(n)), então d(n) + e(n) ∼ O(f (n) + g(n))
Se d(n) ∼ O(f (n)) e e(n) ∼ O(g(n)), então d(n)e(n) ∼ O(f (n)g(n))
Se d(n) ∼ O(f (n)) e f (n) ∼ O(g(n)), então d(n) ∼ O(g(n))
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
11 / 1
Complexidade do método da bolha (bubble-sort)
Façamos a análise de complexidade do método da bolha:
Efectivamente, o número de iterações total é a soma das iterações que o
ciclo j faz para cada valor de i, i.e.
Pn−1
i=1 (n
− i)
= (n − 1) + (n − 2) + . . . + 2 + 1 =
=
n(n−1)
2
Fernando Silva (DCC-FCUP)
=
n2
2
−
n
2
⇒ O(n2 )
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
12 / 1
Complexidade de funções recursivas
Considere-se a função factorial fact() e seja T (n) o tempo de execução
para fact(n), então:

c + T (n − 1),
∴ T (n) =
d,
se n > 1
se n ≤ 1
assumindo n ≥ 2: T (n − 1) = c + T (n − 2) ⇒ T (n) = 2c + T (n − 2)
em geral: T (n) = ic + T (n − i), n > i
se i = n − 1, então T (n) = c(n − 1) + T (1) = c(n − 1) + d
donde podemos concluir T (n) ≈ O(n), i.e. fact() tem complexidade n.
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
13 / 1
Complexidade da pesquisa binária (1)
Considere-se o método pesqbin() (pesquisa binária não recursiva):
Inicialmente o intervalo de valores é n (e = 0 e d = n − 1). Em cada
passo do ciclo, o intervalo reduz-se a metade.
Portanto, a questão que se coloca é:
I
I
dado um inteiro n, quantas divisões inteiras por 2 são necessárias para
que chegue a 1?
i.e. qual dos valores seguintes será o primeiro a ser < 1?
n/2, n/4, n/8, . . . , n/2k , . . .
k < 1,à Complexidade
7. Introdução
Temos de resolver n/2
o que dádekAlgoritmos
> log2 n
Fernando Silva (DCC-FCUP)
Estruturas de Dados
14 / 1
Complexidade da pesquisa binária (2)
É necessário resolver a equação: n/2k < 1
se aplicarmos logaritmos, temos k > log2 n
Podemos então dizer que:
I
com k = dlog2 ne sabemos que ao fim de um máximo de k iterações,
encontramos o valor ou podemos concluir que o valor que procuramos
não existe.
Em resumo, dizemos que a função pesqbin() tem complexidade
logarítmica, O(log2 n), pois o número de iterações necessárias não
excede log2 n, sendo n a dimensão dos dados.
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
15 / 1
Complexidade de árvores binárias de pesquisa (1)
Ver primeiro capítulo sobre árvores!
Se inserirmos n valores aleatórios numa árvore binária de pesquisa,
sabemos que
I
I
o comprimento médio do caminho da raíz até uma folha é O(log2 n) –
correspondente à profundidade da árvore.
verificar se x pertence à árvore é assim O(log2 n)
Se a árvore for completa, então nenhum caminho da raíz até um dado
nó pode ter mais do que 1 + log2 n nós.
I
métodos insertBTNode(), contains() e removeBTNode() são
O(log2 n).
É comum que ao inserirmos n valores aleatórios, a árvore não seja
completa, pode até ficar uma sequência ordenada. Neste caso cada
inserção é O(n).
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
16 / 1
Complexidade de árvores binárias de pesquisa (2)
A questão a saber é
I
I
se uma árvore binária em média estará próxima de uma árvore
completa ou de uma sequência?
isto decide se o tempo médio é O(log2 n) ou O(n).
A demonstração deste resultado é complexa, envolvendo
probabilidades, basta-nos aqui saber que é possível mostrar por
indução que a complexidade será O(log2 n).
Fernando Silva (DCC-FCUP)
7. Introdução à Complexidade de Algoritmos
Estruturas de Dados
17 / 1
Download