1 1 1 Algoritmo

Propaganda
UNDB
ESTRUTURAS DE DADOS
Prof. Alessandro Gonçalves
[email protected]
Complexidade de Algoritmos
Conceituação
Complexidade no pior caso, melhor caso e caso médio
Exemplos
Complexidade de Algoritmos
Avaliação de tempo na história:
1) Algoritmos primitivos
2) A avaliação do tempo na matemática.
– Ex: tábuas de Log
3) O aparecimento do computador
– O tempo como fator primordial
Complexidade de Algoritmos
Avaliação de espaço na história:
1) No início era fundamental
– Ex: quanto de memória tenho ?
– Eniac: 200 bits
2) Hoje já não é tão importante
– Era da fartura
Complexidade de Algoritmos
Dois métodos para avaliar o tempo: Empírico e Analítico
Empírico
1) Medição do tempo de execução do algoritmo
2) Dependentes do hardware (memória, computador...) e
software (compilador, linguagem...)
3) Permitem tratamento estatístico
4) Mais simples de ser implementado
Complexidade de Algoritmos
Dois métodos para avaliar o tempo: Empírico e Analítico
Analítico
1) Expressões matemáticas para determinar o tempo
2) Independentes do hardware (memória, computador...) e
software (compilador, linguagem...)
3) Permitem tratamento estatístico
4) Mais complexo de ser implantado
Complexidade de Algoritmos
Implantação do método Analítico
1) Considera-se grande quantidade de dados
2) Valores assintóticos
3) Desconsiderar constantes aditivas e multiplicativas
– Ex: 2*n² + 10x + 5 é equivalente a n² + x.
– As duas expressões acima são da ordem n²
4) Baseado em uma variável independente, na entrada do
algoritmo(caixa preta)
5) Mais complexo de ser implantado
Complexidade de Algoritmos
Definindo uma expressão matemática
1) Divide-se o algoritmo em passos
2) Cada passo é composto de número fixo de operações
básicas
3) A operação básica de maior frequência é conhecida como
“operação dominante”.
4) O número de passos do algoritmo é a frequência da
operação dominante.
5) Em algoritmos de ordenação, geralmente a operação
dominante é a comparação.
Complexidade de Algoritmos
Exemplo em C – inverte.c
Resumo:
void inverte() {
int x, temp;
for (x = 0; x<5; x++) {
temp = vet[x];
vet[x] = vet[9-x];
vet[9-x] = temp;
}
}
Cada passo corresponde a troca entre dois elementos
Variável independente: número de elementos (n)
Número de passos: número de execuções do bloco
Complexidade de Algoritmos
Soma de matrizes (para a turma resolver)
2 3 5
0 0 2
2 3 7
0 1 2
3 -1 4
3 0 6
3 0 1
-4 1 0
-1 1 1
Algoritmo:
Para i = 1 até n faça
Para j = 1 até n faça
Cij = Aij + Bij
Fim Para J
Fim Para i
Variável independente ?
Número de linhas da matriz
Número de passos ?
N²
Complexidade de Algoritmos
Multiplicação de matrizes (para a turma resolver)
2 5 9
2 7
69 47
3 6 8
4 3
70 55
5 2
Algoritmo:
Para i = 1 até n faça
Para j = 1 até n faça
Dij = 0
Para k = 1 até n faça
Dij = Dij + Aik * Bkj
Variável independente ?
...
Número de colunas da matriz A
Número de passos ?
N³
Complexidade de Algoritmos
Definindo uma expressão matemática
Nos exemplos anteriores, o número de passos dependia
sempre do tamanho da entrada, não do seu valor.
Mas isso nem sempre ocorre. Em geral, o número de passos
depende do valor da entrada.
Considere:
Duas matrizes A e B e uma variável X.
Se X = 0, faça C = A+B
Se X <>0, faça D = A.B
Número de passos ?
N² ou N³
Complexidade de Algoritmos
Definindo uma expressão matemática para Complexidade de
Tempo
Ideal seria sempre conhecer o número de passos, conforme
a entrada
Difícil de ser atingido na prática
Alternativa: determinar o número de passos para entradas
específicas e representativas
Complexidade de Algoritmos
Determinando entradas representativas
A = Algoritmo
E = {E1, E2..., En}
T1 = número de passos de A, quando a entrada for Ei
Complexidade de Algoritmos
Complexidade do Pior Caso
Número de passos da entrada mais desfavorável
A mais utilizada
Quase sempre é relevante(Ex: aplicações de segurança)
Quando falo que um algoritmo tem uma Complexidade “X”, estamos falando
da Complexidade do Pior Caso
Complexidade do Melhor Caso
Número de passos da entrada mais favorável
Pouco utilizada
Pouco relevante
Aplicações específicas
Complexidade do Caso Médio
Número de passos da entrada média
Relevante
Tratamento matemático e geralmente, complexo pois depende da
probabilidade
Complexidade de Algoritmos
q = 0.5 ou 50%
Complexidade de Algoritmos
Exercícios (20 minutos)
1) Calcule a complexidade do algoritmo para calcular n!
2) Sejam duas matrizes: (aij) e (bkj) tais que:
1 < i < n; 1 <= k<= n; 1<= j <= m, escrever os algoritmos
para fazer
C=A+ B
D=A*B
Determinar as complexidades
Complexidade de Algoritmos
Solução dos exercícios
Soma := 0
Para i = n até 1 passo -2 faça
Soma := Soma + n*(n-1);
Fim Para
Complexidade: n
Complexidade de Algoritmos
Solução dos exercícios
Algoritmo: soma de matrizes
Para i := 1 até n faça
Para j := 1 até p faça
Cij := aij + bij
Complexidade = n.p
Complexidade de Algoritmos
Solução dos exercícios
Algoritmo: multiplicação de matrizes
Para i := 1 até n faça
Para j := 1 até p faça
Dij = 0
Para k := 1 até p faça
Dij := Dij + aik * bkj
Complexidade = n.p.k
(linhas da matriz A)
(colunas da matriz B)
Complexidade de Algoritmos
Análise de algoritmo
Demo (A,n) {
Entrada: um array A[] com n elementos inteiros
Saída: o maior elemento em A[];
Int c;
C = A[0];
For (i = 1; i < n; i ++) {
If (c < A[i])
c = A[i];
}
Return c;
}
Quantas operações primitivas são necessárias para a execução ?
Complexidade de Algoritmos
Análise de algoritmo
1) inicializar a variável array como A[0]. Duas operações primitivas
2) o contador i é inicializado com o valor 1 no início do laço for.
Corresponde a uma operação primitiva
3) a condição i < n é verificada antes de entrar no laço for. Uma
operação primitiva de comparar dois números;
4) o contador i é inicializado em 0 e incrementado em 1 no fim de
cada iteração do laço, a comparação i < n é feita n vezes, assim a
condição contribui com n unidades para a contagem
Complexidade de Algoritmos
Análise de algoritmo
5) o laço for é executado n-1 vezes. A cada iteração, A[i] é
comparado com c (duas operações primitivas indexação e
atribuição). O contador i é incrementado. Duas operações
primitivas, soma e atribuição. Assim, a cada iteração do laço quatro
ou seis operações são realizadas, dependendo se A[i] < c ou A[i] >
c. Desta forma, o corpo do laço contribui para a contagem variando
de 4(n-1) ou 6(n-1)
6) retorna o valor da variável que corresponde a uma operação
primitiva e é executada apenas uma vez.
Resumo
Melhor caso: 2 + 1 + n + 4(n-1) + 1 = 5n
Pior caso: 2 + 1 + n + 6(n-1) + 1 = 7n - 2
Complexidade de Algoritmos
Notação O (Omicron)
Refere-se ao pior caso
Melhor caso: 2 + 1 + n + 4(n-1) + 1 = 5n
Pior caso: 2 + 1 + n + 6(n-1) + 1 = 7n – 2
=> n
=> n
O(n) = f(x) = 7n -2
Para calcularmos O, consideramos sempre o valor mais relevante,
em termos de “n” ou outras variáveis envolvidas
Complexidade de Algoritmos
Exercícios
1) n³ -1
2) n² + 2.log n
n
n
3) 3.n + 5.2
n
n-1
4) (n-1) + n
n
n²
5) 5.3 + 4.2
6) 6.347.562
7
n
7) 5.n + 3.2 + n!
8) 3n + 7m + 2
9) 5n² + 9m + 4
10) 3n + 5m + n.m
Complexidade de Algoritmos
Respostas
1) O(n³)
2) O(n²)
n
3) O(n)
n
4) O(n)
n²
5) O(2)
6) O(1)
7) O(n!)
8) O(n + m)
9) O(n² + m)
10) O(n.m)
Complexidade de Algoritmos
Escalas
N
log2n
n
n.log2n
n²
n³
2n
n!
1
0
1
0
1
1
2
1
10
3.32
10
33
100
1000
1024
3x10 6
100
6.64
100
664
10.000
1.000.000
1,28 x 1030
3x10157
9.97
1000
n!
2n
9970
n²
1.000.000
109
1,072 x 1031
3x102567
1000
O(n)
n.log2n
n
log2n
n
Complexidade de Algoritmos
Propriedades da notação O
O(g + h) = O(g) + O(h)
O(g . h) = O(g) . O(h)
O(k . g) = k . O(g) = O(g)
Complexidade de Algoritmos
Video Torre de Hanoi
Programa Torre de Hanoi em C
Para solucionar um Hanói de 64 discos, são necessários 18.446.744.073.709.551.615
movimentos
Complexidade de Algoritmos
Propriedades da notação O
Cota superior – menor complexidade de um algoritmo conhecido
Nos exemplos anteriores, a complexidade de multiplicação de
matrizes era O(n³)
O(n³)
O algoritmo de Strassen diminuiu a complexidade para O(n2,807)
O(n2,807)
O(n³)
O algoritmo de Coppersmith e Winograd melhoraram para O (n2,376)
O (n2,376)
O(n2,807)
O(n³)
Complexidade de Algoritmos
Notação Ɵ (Teta)
Refere-se ao caso médio
Este é o caso que é o mais difícil de ser determinado, pois,
necessita de análise estatística e em conseqüência de muitos
testes, contudo é muito utilizado, pois é o que representa mais
corretamente a complexidade do algoritmo.
Exemplo: Procurar uma palavra em um dicionário. Pode-se iniciar a
busca de uma palavra na metade do dicionário. Imediatamente se
sabe se foi encontrada a palavra ou, no caso contrário, em qual das
duas metades deve se repetir o processo (é um processo recursivo)
até se chegar ao resultado. Em cada busca (ou sub-busca), o
problema (as páginas em que a palavra pode estar) vão se
reduzindo à metade, o que corresponde com a função logarítmica.
Este procedimento de busca (conhecido como busca binária) em
uma estrutura ordenada têm complexidade logarítmica.
Ɵ(log2n)
Complexidade de Algoritmos
Notação Ω (ômega)
Refere-se ao melhor caso
Pouco utilizado porque sempre precisamos saber como o algoritmo
se comporta em situações difíceis (pior caso).
Exemplo:
Exemplo 1: Em uma lista telefônica queremos encontrar um
número, assume-se que a complexidade do caso melhor é Ω (1),
pois está pressupondo-se o número desejado está na primeira
posição.
Exemplo 2: Extrair qualquer elemento de um vetor. A indexação em
um vetor ou array, leva o mesmo tempo seja qual for o índice que
se queira buscar. Portanto é uma operação de complexidade
constante Ω (1).
Complexidade de Algoritmos
Conclusão
Nas complexidades algorítmicas temos:
Ω( ) <= θ( ) <= O()
Algoritmos ótimos podem ser obtidos de duas formas:
1) melhoramento interno do código OU
2) comparação dos algoritmos entre si, escolhendo o de menor
complexidade.
exemplo
Complexidade de Algoritmos
UNDB
ESTRUTURAS DE DADOS
Prof. Alessandro Gonçalves
[email protected]
Download