Escolar Documentos
Profissional Documentos
Cultura Documentos
Aula 2
Aula 2
Aula 2
Prof. Sergio Jeferson Rafael Ordine
12 de Fevereiro, 2011
1 inı́cio
2 para j ← 2 a n faça
3 elementoAtual ← v[j]
4 i←j−1
5 enquanto i>0 E v[i]>elementoAtual faça
6 v[i + 1] ← v[i]
7 i←i−1
8 fim
9 v[i + 1] ← elementoAtual
10 fim
11 fim
Este algoritmo percorre o vetor desde sua segunda posição até a última,
armazenando o elemento desta posição. Em seguida o laço nas linhas 5 a
8 ”empurra”os elementos maiores que ele uma posição a frente e por fim
insere o elemento na posição correta (por isso seu nome).Como o vetor é
ordenado posição a posição sempre teremos um vetor parcialmente ordenado
1
e ao empurrarmos para frente todos os elementos maiores que o elemento j
isto nos garante que mantemos a ordenação a cada passo.
Este procedimento é muito similar a forma como arrumamos um jogo de
cartas na mão em alguns jogos de baralho.
Para analisarmos este algoritmo adotaremos um método bem mais siste-
mática que o adotado na aula passada. Vamos considerar que cada comando
tem um custo de execução (para executá-lo uma vez) e que este comando
será executado determinado número de vezes. Com isto teremos a seguinte
lista de custos/tempo:
8 c7 n−1
2
• Os comandos dentro deste laço executam uma vez a menos que o pró-
prio laço (lembrando que contamos o caso em que a condição se torna
inválida). Isto nos dá a somatória onde subtraimos 1 de cada elemento
tj para representar este fato.
n
X n
X n
X
T (n) = c1 n+c2 (n−1)+c3 (n−1)+c4 tj +c5 (tj −1)+c6 (tj −1)+c7 (n−1)
j=2 j=2 j=2
T (n) = c1 n + c2 (n − 1) + c3 (n − 1) + c4 (n − 1) + c7 (n − 1)
T (n) = c1 n + c2 n − c2 + c3 n − c3 + c4 n − c4 + c7 n − c7
T (n) = an − b
Como todos os custos são constantes, sua soma foi substituida pelas cons-
tantes a e b e vemos que este algoritmo executa, no melhor caso, de acordo
com uma função linear ao tamanho de sua entrada.
Por outro lado, o pior caso seria aquele em que mais trocas são feitas para
posicionar corretamente cada elemento. Isto ocorre no caso do vetor estar
inicialmente ordenado de forma decrescente.
Neste caso, tj = j, pois temos que realizar j −1 trocas para cada elemento
e mais uma execução quando a condição se torna inválida. Assim sendo
t2 = 2, t3 = 3, ... tn = n. Considerando isto temos que as somatórias
assumirão os seguintes valores:
n
X n(n − 1)
j= −1
j=2
2
3
n
X n(n − 1)
(j − 1) =
j=2
2
c4 c5 c6 2 c4 c5 c6
T (n) = ( + + )n + (c1 + c2 + c3 − − − + c7 )n − (c2 + c3 + c4 + c7 )
2 2 2 2 2 2
T (n) = an2 + bn + c
No pior caso, então, este algoritmo roda em um tempo quadrático em
relação ao tamanho do vetor de entrada.
Como falamos de algoritmos esta função tem como domı́nio os números
inteiros (pois não existe entrada não inteira para o algoritmo), porém pode-
mos estender este conceito (mantendo alguma atenção em situações onde isto
pode gerar problemas) para que o domı́nio da função seja os números reais.
Com isto podemos utilizar as notações abaixo.
2 Notação Assintótica
Se olharmos a função an2 + bn + c vemos que quanto maior n se torna, menor
será a parcela no valor total representada pelos valores de bn e c, pois o termo
quadrático cresce de forma muito mais rápida.
Como em geral estamos interessados em uma ordem de grandeza de uso
de um recurso (em geral tempo de execução) de um algoritmo, uma análise
detalhada como a que fizemos acima acaba sendo muito trabalhosa e pouco
prática. Queremos um método mais rápido para achar um termo ”domi-
nante”da função, quando temos um valor de entrada suficientemente grande.
A notação assintótica nos fornece exatamente isto: um ferramental mate-
mático para considerar apenas o ”termo dominante”de uma função, descon-
siderando constantes que o multiplicam e termos menos significativos.
Assintótico significa ”linha que se aproxima indefinidamente de uma curva
sem jamais cortá-la”.
4
2.1 Notação Θ
Dada uma função f (n), denotamos por Θ(g(n)) o conjunto de funções que
satisfaz o seguinte critério:
c1 n2 ≤ 3n2 + 2n ≤ c2 n2 =
2
c1 ≤ 3 + ≤ c2
n
O termo n2 é menor ou igual a um para n ≥ 2 e diminui quanto mais o
valor de n aumenta. Logo se assumirmos c1 = 2 e c2 = 4 a expressão acima
é válida para todo n ≥ n0 = 2 . Como isto é verdade, podemos dizer que
f (n) ∈ Θ(n2 ()). Em geral usamos a notação f (n) = Θ(n2 ()). Veremos que
esta notação pode ser útil em algumas situações.
2.2 Notação O
A notação Θ(g(n)) denota um limite extrito. Podemos aplicar este conceito
também para um limite superior. De forma similar, existe a notação O(g(n))
(em inglês Big-Oh):
Esta notação é muito útil, pois muita vezes permite definirmos um limite
superior para o tempo de execução de um algoritmo meramente olhando para
sua estrutura. No caso do Insertion Sort, como temos dois laços aninhados
que podem no pior caso percorrer quase todo o vetor, temos que o tempo de
execução é limitado por O(n2 ).
5
2.3 Notação Ω
A notação Ω(g(n)) indica um limite inferior para um conjunto de funções.
Podemos defini-la como:
6
3 Lista de Exercı́cios
1. Após analisar um algoritmo identificou-se que seu tempo de execução
respeita a função 7n + 4, onde n é o tamanho da entrada. Podemos
dizer que este algoritmo tem tempo de execução O(n2 )? Explique.
(a) 7 = O(n)
(b) 7n = Θ(n)
(c) 7 = Θ(n)
(d) 3x + 2 = Ω(x)
(e) n2 = O(2n )
(f) 2n = O(n2 )
n(n+1)
(g) 2
= Ω(n)
√
(h) n = O(n)