Você está na página 1de 22

DIVIDE E CONQUISTA

Divide e Conquista
Divide e conquista provavelmente a tcnica
geral de algoritmo mais conhecida.
Os algoritmos com estratgia divide e
conquista seguem os seguintes passos:
1. A instncia do problema dividida em pequenas
instncias do problema (preferencialmente com
o mesmo tamanho)
2. As instncias pequenas do problemas so
resolvidas(tipicamente recursivamente, alem de
que, muitas vezes um algoritmo diferentes
empregado quando as instancias tornam-se
muito pequenas)
3. Se necessrio, as solues obtidas para
instancias pequenas do problema so
combinadas para se obter soluo original.
Divide e conquista
Consideremos o problema de
clculo da soma de nmeros
a
0
, , a
n1
. Se n>1, podemos
dividir o problema em duas
instncias do mesmo problema:
Calcular a soma dos primeiros
1/2 e do restantes 1/2( nmeros.
Se n = 1, retornamos simplesmente
a
0
Depois do calculo de cada soma
podemos adiciona-los para se obter
a soma total:
a
0
++a
n1
=(a
0
+ +a
1/21
)
+(a
1/2
+ +a
n1
)

Problema de
tamanho n
Subproblema
1de tamanho
n/2
Subproblema
2de tamanho
n/2
Soluo do
subproblema 1
Soluo do
subproblema 2
Soluo do
problema original
Exemplo
O exemplo do clculo da soma ilustra o caso
mais tpico da estratgia divide e conquista:
um problema de tamanho n dividido em duas
instncias de tamanho n/2. Mais genericamente,
uma instncia de tamanho n pode ser dividido em
vrias instncias de tamanho n/b, com a deles
precisando ser resolvido. (Aqui, a e b so
constantes; a1 e b>1). Assumindo que o tamanho
n uma potncia de b, para simplificar nossa
anlise, temos a recorrncia a seguir para o tempo
de execuo T(n):
T(n)=aT(n/b) + f(n) (4.1)
Onde f(n) a funo que conta o nmero de vezes
que efectuada a diviso do problema em pequenos
problemas e a combinao das suas solues.


Teorema de Mestre
Recorrncia 4.1 chamado de relao geral de divide
e conquista. Obviamente, a ordem de crescimento de
sua soluo T(n) depende dos valores das constantes a
e b e a ordem de crescimento da funo f(n).
A anlise de eficincia dos algoritmos de tipo divide e
conquista simplificada pelo seguinte algoritmo:
Teorema:
Se f(n)eO(n
d
) onde d0 na equao de recorrncia 4.1,
ento




Este resultado tambm valido para as notaes de O e
O.


d
d
d
a
d
d
b a
b a
b a
Se
Se
Se
n
n n
n
n T
b
>
=
<

O
O
O
e
) (
) log (
) (
) (
log
Exemplo
Como por exemplo, a recorrncia para
o nmero de adies A(n) pelo
algoritmo divide e conquista do
clculo da soma com tamanho de
entrada n=2
k

A(n)=2A(n/2)+1
Assim, a=2, b=2 e d=0 ento a>b
d
,
A(n)eO(n
log
b
a
) = O(n
log
2
2
)=O(n).
Mergesort (ordenao
interlao)
Mergesort um exemplo perfeito de aplicao com sucesso da
estratgia divide-e-conquista. Este ordena um dado vector A[0..
n1] da seguinte maneira:
1. divide o mesmo em duas partes A[0..n/21] e A[n/2 .. n1]
2. Ordenada cada uma delas recursivamente
3. Una os dois pequenos vectores ordenados num nico.

Algoritmo Mergesort(A[0..n1])

se n > 1 ento
copia A[0 .. n/21] para B[0..n/21]
copia A[ n/2 .. n1] para C[0 .. n/2(1]
Mergesort(B[0 .. n/21] )
Mergesort(C[0 .. n/2(1] )
Merge(B, C, A)


Algoritmo Merge(B[0..p1], C[0..q1], A[0..p+q1])

i0, j0, k0;
enquanto i<p E j<q faa
se B[i] <= C[j] ento
A[k] B[i]
i i+1
seno
A[k] C[j];
j j+1;
fimse
k k+1
se i=p ento
copia C[j..q1] para A[k..p+q1]
seno
copia B[i..p1] para A[k..p+q1]
fimse
fimenquanto

8 3 2 9 7 1 5
4
7 1 5 4
8 3 2 9
2 9 8 3
8 3
3 8
2 9
2 9
2 3 8 9
5 4
7 1
7 1
1 7
5 4
4 5
1 4 5 7
1 2 3 4 5 7 8
9
Eficincia para Mergesort (intercalao)
Assumindo que n uma potncia 2, a relao de recorrncia
para o nmero de comparaes C(n)

C (n)=2C (n/2)+C
merge
(n) para n>1, C (1)=0.

Vamos analisar C
merge
(n), o nmero de comparaes feitas
durante a etapa da intercalao. Em cada etapa,
exactamente uma comparao feita, aps o qual o nmero
total de elementos de duas matrizes ainda precisando de ser
processado reduzido a um. No pior dos casos, nenhum dos
dois vectores torna-se vazia antes do outro conter apenas
um elemento (exemplo, pequenos elementos podem ser
provenientes de vectores alternadas). Assim, para o pior
caso, C
merge
(n)=n1 e a recorrncia fica:

C
pior
(n) = 2C
pior
(n/2) + n 1 para n>1, C
pior
(1) = 0
Usando o teorema anterior temos:
C
pior
(n) = nlog
2
n n +1
Quicksort (Ordenao rpida)
O Quicksort, como o Mergesort, se baseia no princpio
da diviso e conquista mas por possuir uma
abordagem diferente no necessita de espao de
memria adicional, o que pode vir a justificar o motivo
dele ser mais utilizado do que o Mergesort.

Sua desvantagem ocorre quando a diviso do vector
(que baseada em comparao) fica muito
desbalanceada (Isto ocorre quando: o vector est
quase ordenado/desordenado ou estar completamente
ordenado/desordenado).

Mesmo com essa desvantagem provado que em
mdia seu tempo tende a ser muito rpido [Cormen,
2002], por isso o nome, Ordenao-Rpida (ou Quick-
Sort em ingls).


Quicksort
Ao contrrio do mergesort, que divide seus elementos
de entrada, de acordo com sua posio no vector,
quicksort os divide de acordo com seu valor.
Especificamente, ele reorganiza elementos de um dado
vector A[0..n1] para encontrar a sua partio, uma
situao onde todos os elementos antes de alguma
posio s so menores ou iguais a A[s] e todos os
elementos aps a posio s so maiores ou iguais a
A[s]

A[0] A[s1] A[s] A[s+1] A[n1]
todos so s A[s] todos so A[s]

Obviamente, depois de uma partio tenha sido feita,
A[s] estar em sua posio final no vector ordenado, e
podemos continuar ordenar os dois subvectores dos
elementos anteriores e posteriores de A[s] de forma
independente.
Quicksort - Algoritmo
Algoritmo quicksort(A[l .. r])
//ordena subvector usando quicksort
//Entrada: A subvector A[l .. r] de A[0 .. n1],
//definida pelos seus ndices a esquerda l e a direita r
//Saida: O subvector A[l .. r] ordenada em ordem crescente
se l < r ento
s particao(A[l .. r])
quicksort(A[l .. s1])
quicksort(A[s+1.. r])

quicksort
A partio de A[0 .. n1] e, mais genericamente, dos seus subvectores A[l ..
r] (0sl<r s n1) pode ser obtida pelo algoritmo a seguir:
Primeiro, seleccione um elemento cujo valor a partir da qual ser divido
os subvectores. Por causa de seu papel orientador, chamamos esse
elemento piv. Existem diversas estratgias para seleccionar um piv.
Por agora, ns usamos a estratgia mais simples i.e., seleccionamos o
primeiro elemento da subvector p=A[l].
Usamos um mtodo eficiente, baseado em duas varreduras do subvector:
um da esquerda para a direita e outro de direita para a esquerda,
cada um comparando os elementos do subvector com o piv.
A varredura da esquerda para a direita inicia-se com o segundo
elemento. Como queremos que os elementos menores que o piv para a
primeira parte do subvector, esta verificao salta todos os elementos
que so menores que o piv e pra ao se deparar com o primeiro
elemento maior ou igual ao piv.
A varredura da direita para a esquerda comea com o ltimo elemento do
subvector. Como os elementos maiores que o piv devem estar na
segunda parte do subvector, esta verificao salta todos elementos que
so maiores que o piv e pra ao se deparar com o primeiro elemento
menor ou igual ao piv.
Quicksort
Trs situaes podem ocorrer, dependendo da existncia ou no do cruzamento dos ndices
de varredura:
Se ndices de varredura i e j no se cruzarem, ou seja, i<j, simplesmente troca-se A[i] e A[j] e
retoma-se as varreduras, incrementando i e decrementando j, respectivamente.



Se os ndices de varredura se cruzarem, ou seja, i>j, o subvector particionado depois da troca do
piv com A[j].



Finalmente, se os ndices de varredura pararem apontando para o mesmo elemento, ou seja, i=j, o
valor apontado deve ser igual a p. Assim, temos o subvector particionada: Podemos considerar o
ltimo caso com o caso de cruzamento de ndices (i>j) trocando o piv com o A[j] para qualquer i>j.


.


i j
p todos so s
p

p
s
p
todos so
p
j i
p todos so s
p
s
p
p todos so
p
i=j
p todos so s
p
= p todos so
p
Algoritmo de partio
Algoritmo particao(A[e..d])
//partio de subvector usando o primeiro elemento como piv
//Entrada: O subvector A[e..d] de A[0..n1], definida pela esquerda e
// direita pelos seus ndices e e d ( e<d) respectivamente.
//Saida: A partio de A[e..d]
pA[e]
ie;
jd+1
repet
repet ii+1 ate que A[i]p
repet jj1 ate que A[j]sp
troca(A[i], A[j])
ate que i j
troca(A[i], A[j]) //desfaz a ltima troca se i j
troca(A[l], A[j])
retorna j
Exemplo
i j
5 3 1 9 8 2 4 7
i j
5 3 1 9 8 2 4 7
i j
5 3 1 4 8 2 9 7
i j
5 3 1 4 8 2 9 7
i j
5 3 1 4 2 8 9 7
j i
5 3 1 4 2 8 9 7
2 3 1 4 5 8 9 7
i j
2 3 1 4 5 8 9 7
i j i j
2 3 1 4 8 9 7
i j i j
2 1 3 4 8 7 9
j i j i
2 1 3 4 8 7 9
1 2 3 4 7 8 9
1 ij
3 4 7 9
j i
3 4
4
1 2 3 4 5 7 8 9
Ordena a lista 5,3,1,9,8,2,4,7 em ordem crescente
Quicksort - complexidade
Pode-se notar que o nmero de comparaes
feitas antes da realizao da partio n+1se a
varredura de ndices se cruzam e n se eles
coincidem. Se a separao acontecer no meio
do subvector teremos o melhor caso. O nmero
de comparaes no melhor caso, C
ml
ira
satisfazer a recorrncia
C
ml
(n)=2C
ml
(n/2)+n para n>1,
C
ml
(1)=0
Segundo o teorema de Mestre, C
ml
(n)e(nlog
2
n)
Resumo
Melhor Caso: (n log
2
n);
Caso Mdio: Tende a ser (n log
2
n); (TPC)
Pior Caso: (n). (TPC)
Busca binria
A busca binria um eficiente algoritmo para pesquisa numa lista
ordenada.
Funcionamento
Compara a chave da busca k com elemento mdio da lista A[m].
Se eles coincidem o algoritmo pra, seno, a mesma operao
repetida recursivamente para primeira metade da lista se k<A[m]
e segunda metade se k>A[m];
k

A[0]A[m-1] A[m] A[m+1]A[n1]



pesquisa-se
neste lado de
k<A[m]
pesquisa-se
neste lado de
k>A[m]
Busca binria-Exemplo
Aplique a busca binria para pesquisar k=70 na
lista 3,14,27,31,39,42,55,70,74,81,85,93,98
Soluo:

ndice 0 1 2 3 4 5 6 7 8 9 10 11 12
Valores 3 14 27 31 39 42 55 70 74 81 85 93 98
Iterao
1
e m d
Iterao
2
e m d
Iterao
3
e,m d
algoritmo
Algoritmo BuscaBinaria(A[0..n1], k )
//implementao no recursiva de busca binria
//Entrada: O vector A[0..n1],em ordem crescente e a chave de busca k
//Sada: retorna o ndice do elemento no vector igual a k ou -1 caso contrrio
e0
dn 1
enquanto e sd faca
m (e+d)/2
se k=A[m] ento
retorna m
seno se k <A[m] ento
dm1
seno
em+1
retorna -1
Eficiencia
A forma padro de anlise de eficiencia do algoritmo de
busca binria a contagem de nmero de vezes que a chave
de busca comparada com os elementos na lista. Portanto,
para simplificar este processo, utilizemos a comparao em 3
sentidos (<, > ou =). Isto quer dizer que depois da
comparao de k com A[m], o algoritmo pode dizer se k
menor, ou igual, ou maior que A[m]
Quantos comparaes so executadas no algoritmo? A
resposta no depende somente de n mas tambem na
especificao particular da instncia do problema.
Seja C(n) o nmero de comparao executadas no algoritmo
no pior caso. As entradas para pior caso inclui todo vector
que no contem a chave(obviamente, alguns casos a busca
com sucesso). Como depois da comparao o algoritmo faz
o mesmo para outra metade, obtemos a seguinte relao de
recorrencia:
C(n) = C(n/2) +1 para n>1, C(1) = 1

Você também pode gostar