NOÇÕES DE ANÁLISE DE
COMPLEXIDADE
NOTAÇÃO ASSINTÓTICA
A notações que usamos para descrever o tempo de
execução assintótica de um algoritmo são definidas em
termos de funções cujos domínios são o conjunto dos
números naturais
N ={0,1,2,...}.
NOTAÇÃO ASSINTÓTICA
NOTAÇÃO
ᷴ
Também conhecido como limite assintótico firme.
Ao analisarmos o tempo de execução do algoritmos de ordenação por inserção, verificar-se-a que o algoritmos tem o tempo médio de execução de T(n) = ᷴ(n²), o que quer dizer que no caso médio ele executa em n² onde n é o número de entradas.
NOTAÇÃO
ᷴ
ᷴ
(g(n)) = {f(n): existem constantes
positivas c
1, c
2e n
0tais que 0≤c
1g(n)
≤c
2g(n) para todos n≥n
0}
Uma função f(n) pertence ao conjunto
ᷴ
(g(n)) se existem constantes c
1e c
2NOTAÇÃO
ᷴ
A definição de
ᷴ
(g(n)) exige que todo membro f(n)
∈
ᷴ
(g(n)) seja
positivo para um determinado n suficientemente grande.
Vamos usar a definição formal para mostrar que ½n²-3n =
ᷴ
(n²)
c
1n²
≤
½n²-3n
≤
c
2n² ,
n
≥
n
0.
A divisão por n² produzc
1≤
½- 3/n
≤
c
2 Fazendo:NOTAÇÃO
ᷴ
c
2≥
½- 3/n
a desigualdade é válida para
n
≥
1
pois para qualquer
valor menor que
1, -3/n
cresce em módulo
n
∈
ℕ
.
Temos que
½
≥
½ - 3/n
n
∈
ℕ
é verdadeiro logo podemos tomar c
2com valor de ½
logo temos c
2=½ .
c
1≤
½- 3/n
c
1-½
≤
- 3/n
n
≥
3/(½ -c
1)
para satisfazer a
desigualdade
c
1<½
tomando c
1=1/14 por exemplo temos que
NOTAÇÃO
A notação
ᷴ
limita assintoticamente
uma função acima e abaixo. Quando
temos um limite superior , usamos a
notação
que é um limite
assintótico superior.
Para uma dada função g(n), denotamos
(g(n))
o conjunto das funções:
(g(n))
= {f(n): existem constantes
positivas c
e n
0tais que 0≤f(n)≤cg(n)
para todo n≥n
0}
Para todos os valores n à direita de n0 o valorNOTAÇÃO
Usando a notação
, podemos descrever frequentemente o tempo de
execução de um algoritmo apenas inspecionando a estrutura global
do algoritmos.
Por exemplo, a estrutura de loop duplamente aninhado do algoritmo de ordenação por inserção, produz imediatamente um limite superior
(n²)
OPERAÇÕES COM A NOTAÇÃO
f (n) = O(f (n))
c × O(f (n)) = O(f (n)) c = constante
O(f (n)) + O(f (n)) = O(f (n))
O(O(f (n)) = O(f (n))
O(f (n)) + O(g(n)) = O(max(f (n), g(n)))
O(f (n))O(g(n)) = O(f (n)g(n))
NOTAÇÃO
ᵗ
Da mesma maneira que a notação
fornece um limite assintótico
superior a notação
ᵗ fornece umlimite assintótico inferior.
Para uma determinada função g(n), denotamos por ᵗ(g(n)) o conjunto da funções:
ᵗ(g(n)) =
{f(n): existem constantes
positivas c
e n
0tais que 0≤cg(n)≤f(n)
NOTAÇÃO
ᶡ
O limite assintótico fornecido pela notação
pode se ou nãoassintoticamente restrito. O lmite 2n² =
(n²) é assintoticamente restrito,
mas o limite 2n =
(n²) não o é.
ᶡ
(g(n))
= {f(n): para qualquer constante positiva c>0 existe uma
constante n
0>0 tal que 0≤f(n)≤cg(n) para todo n≥n
0}.
Por exemplo 2n=
ᶡ
(n²), mas 2n² ≠
ᶡ
(n²)
Intuitivamente na notação
ᶡ
, a função f(n) se torna insignificante em
relação a g(n) a medida que se aproxima do infinito.
NOTAÇÃO
ᶫ
Por analogia a notação
ᶫ
está para a notação
ᵗ assim como a notaçãoᶡ
está para a notação
. Usamos a notação
ᶫ
para denotar um limite
inferior que não é assintoticamente restrito. f(n)
∈
ᶫ
(g(n)) se e
somente se g(n)
∈
ᶡ
(f(n))
Formalmente definimos
ᶫ
(g(n)) como o conjunt:
ᶫ
(g(n)) = {f(n): para qualquer constante positiva c > 0 existe uma
constante n
0>0 tal que 0≤cg(n)≤f(n) para todo n≥n
0}. Por exemplo:
RELAÇÃO ASSINTÓTICA
A seguinte hierarquia de funções pode ser definida do ponto de
vista assintótico:
CLASSES DE COMPORTAMENTO ASSINTÓTICO
f(n)=O(1) : O uso do algoritmo independe do tamanho de n. As instruções do
algoritmo são executadas um número fixo de vezes.
f(n)=O(log(n)): Ocorre tipicamente em algoritmos que resolvem um problema
transformando-o em problemas menores. Ex:Algoritmo de pesquisa binária.
f(n)=O(n): Em geral, um pequeno trabalho é realizado sobre cada elemento
de entrada.
Esta é a melhor situação possível para um algoritmo que tem que processar/produzir n elementos de entrada/saída.
CLASSES DE COMPORTAMENTO ASSINTÓTICO
f(n) = O(n log n)
-Este tempo de execução ocorre tipicamente em algoritmos que resolvem um problema quebrando-o em problemas menores, resolvendo cada um deles independentemente e depois agrupando as soluções.
-Caso típico dos algoritmos baseados no paradigma divisão-e-conquista.
CLASSES DE COMPORTAMENTO ASSINTÓTICO
f(n)=O(n²)
-Algoritmos desta ordem de complexidade ocorrem quando os itens de dados
são processados aos pares, muitas vezes em um anel dentro do outro
– Para n= 1 000, o número de operações é da ordem de 1 000 000. – Sempre que n dobra o tempo de execução é multiplicado por 4.
– Algoritmos deste tipo são úteis para resolver problemas de tamanhos Relativamente pequenos.
Exemplos:
CLASSES DE COMPORTAMENTO ASSINTÓTICO
f(n) =O(n³)
– Algoritmos desta ordem de complexidade geralmente são úteis apenas para resolver problemas relativamente pequenos.
– Para n = 100 , o número de operações é da ordem de 1 000 000 – Sempre que n dobra o tempo de execução é multiplicado por 8.
– Algoritmos deste tipo são úteis para resolver problemas de tamanhos relativamente pequenos.
Exemplo:
CLASSES DE COMPORTAMENTO ASSINTÓTICO
f(n) = O(2n)
– Algoritmos desta ordem de complexidade não são úteis sob o ponto de vista prático.
– Eles ocorrem na solução de problemas quando se usa a força bruta para resolvê-los.
– Para n = 20 , o tempo de execução é cerca de 1 000 000.
– Sempre que n dobra o tempo de execução fica elevado ao quadrado. Exemplo:
CLASSES DE COMPORTAMENTO ASSINTÓTICO
f(n) =O(n!).
– Um algoritmo de complexidade O(n!) é dito ter complexidade exponencial, apesar de O(n!) ter comportamento muito pior do que O(2n).
– Geralmente ocorrem quando se usa força bruta na solução do problema.
Considerando:
FUNÇÃO DE COMPLEXIDADE
● Usa um modelo matemático baseado em um computador idealizado.
● Deve ser especificado o conjunto de operações e seus custos de execuções.
● É mais usual ignorar o custo de algumas das operações e considerar apenas as operações mais significativas.
Por exemplo, algoritmos de ordenação:
FUNÇÃO DE COMPLEXIDADE
● Para medir o custo de execução de um algoritmo é comum definir uma função de custo ou função de complexidade f .
● f (n) é a medida do tempo necessário para executar um algoritmo para um problema de tamanho n.
● Função de complexidade de tempo: f (n) mede o tempo necessário para executar um algoritmo em um problema de tamanho n.
● Função de complexidade de espaço: f (n) mede a memória necessária para executar algoritmo em um problema de tamanho n.
● Utilizaremos f para denotar uma função de complexidade de tempo.
OPERAÇÕES RELEVANTES
Operações aritméticas
Comparações
Atribuições
Resolver um ponteiro ou referência
Indexação em um arranjo