Vous êtes sur la page 1sur 15

Divide y Vencers

Tcnica de diseo:
Descomponer el caso a resolver en un nmero de subcasos ms
pequeos del mismo problema.
Resolver independientemente cada subcaso.
Combinar los resultados para construir la solucin del caso
original.
Este proceso se debe aplicar recursivamente.

La eficiencia de esta tcnica se debe a cmo se resuelvan


los subcasos.
Programacin III

Divide y Vencers
Esquema genrico
funcin divide_y_vencers (c: tipocaso) : tiposolucin;
var x1, ..., xk : tipocaso; y1, ...,yk: tiposolucin;
si c es suficientemente simple entonces
devolver solucin_simple(c)
sino descomponer c en x1, ..., xk
para i 1 hasta k hacer
yi divide_y_vencers (xi)
fpara
devolver combinar_solucion_subcasos(y1, ..., yk)
fsi
ffuncin
Programacin III

Divide y Vencers
El nmero de subejemplares, k, suele ser pequeo e
independiente de del caso particular a resolver.
Cuando k = 1, el esquema divide_y_vencers pasa a
llamarse reduccin ( simplificacin). En estos casos se
trata de reducir la solucin de un caso muy grande a la de
uno ms pequeo.
Algunos algoritmos de divide_y_vencers pueden
necesitar que el primer subejemplar est resuelto antes de
formular el segundo subejemplar.
Programacin III

Divide y Vencers
Para que el enfoque divide_y_vencers merezca la pena,
se deben cumplir las siguientes condiciones:
Debe ser posible descomponer el caso a resolver en
subcasos.
Se debe poder componer la solucin a partir de las
soluciones de los subcasos de un modo eficiente.
Los subejemplares deben ser, en la medida de lo
posible, aproximadamente del mismo tamao.

Programacin III

Divide y Vencers
Clculo de la complejidad para el caso general
Sea n el tamao de nuestro caso original.
Y sea k el nmero de subcasos.
Supongamos que existe una constante b t.q. el tamao de los k
subcasos es aprox. n/b .
Si g(n) es el tiempo requerido por el algoritmo divide_y_vencers
en casos de tamao n, sin contar el tiempo necesario para realizar las
llamadas recursivas
t(n) = k*t(n b) + g(n)
Donde t(n) es el tiempo total requerido por el algoritmo
divide_y_vencers, siempre que n sea lo suficientemente grande.
Programacin III

Divide y Vencers
Si existe un entero p t.q. g(n) (np), entonces podemos concluir
que:
T(n)

(np)

si k < bp

(np log n)

si k = bp

(nlogbk)

si k > bp

Esta solucin la hemos hallado utilizando la solucin del ejemplo


4.7.13 del libro Fundamentos de Algoritmia.

Programacin III

Divide y Vencers
Falta por ver cundo se deja de dividir el caso en subcasos y se
resuelve con un algoritmo bsico, es decir, cmo se determina el
umbral.
El umbral ser un n0 t.q. cuando el tamao del caso a tratar sea
menor o igual, se resuelva con un algoritmo bsico, es decir, no se
generen ms llamadas recursivas.
La determinacin del umbral ptimo, es un problema complejo. Para
un mismo problema puede variar con la implementacin concreta o
con el tamao de n.
Dada una implementacin particular, puede calcularse
empricamente. Este sistema puede requerir unas cantidades notables
de tiempo de computadora y humano.
Programacin III

Divide y Vencers
Tambin puede emplearse una tcnica hbrida para su
clculo:
Primero se deben obtener las ecuaciones de
recurrencia de nuestro algoritmo (estudio terico).
Determinar empricamente los valores de las
constantes que se utilizan en dichas ecuaciones para la
implementacin concreta que estamos empleando.
El umbral ptimo se estima hallando el tamao n del
caso para el cual no hay diferencia entre aplicar
directamente el algoritmo clsico o pasar a un nivel ms
de recursin.
Programacin III

PROBLEMA: Bsqueda binaria


Sea T[1..n] una matriz t.q.:
T[j] T[i] siempre que n j i 1
Sea x un elemento. El problema consiste en buscar x en la matriz T,
si es que est, es decir, queremos hallar un i t.q.
n i 1 y T[i] x > T[i-1]
T[0] = -
T[n + 1] = +
La aproximacin evidente a este problema consiste en examinar
secuencialmente todos los elementos de T, hasta que encontremos el
elemento buscado o lleguemos al final de la matriz.
Programacin III

PROBLEMA: Bsqueda binaria


funcin secuencial(T[1..n],x)
{Bsqueda secuencial de x en una matriz}
para i 1 hasta n hacer
si T[i] x entonces
devolver i
fsi
fpara
devolver n+1
ffuncin
Programacin III

PROBLEMA: Bsqueda binaria


Es fcil ver que este algoritmo secuencial de bsqueda estar en el
orden de (n) (el caso peor es de orden (n) y el mejor (1)).
Para acelerar la bsqueda podemos aprovechar la propiedad de que la
matriz est ordenada. De este modo podremos dividir la matriz en
dos mitades y buscar el elemento x, all donde estn los elementos
mayores o iguales que l.
1
-5

x = 12

2
-2

3
0

4
3

5
8

6
8

7
9

8 9 10
12 12 26

k
i
i
ik

k
k j
j
ij

11
31

T[k] x ?

j
j

no
s
s
no

i = j alto

Programacin III

PROBLEMA: Bsqueda binaria


Identificacin del problema con el esquema
El problema se puede descomponer en subproblemas de
menor tamao
Se reduce el espacio de bsqueda a la mitad en cada paso
No hay soluciones parciales, la solucin es nica
(la solucin de un nuevo subproblema es la solucin del
problema original)
La descomposicin en subproblemas contina hasta llegar
a la solucin (encontrar el elemento o determinar que no
est )
Programacin III

PROBLEMA: Bsqueda binaria


Pasos del algoritmo de bsqueda binaria :
1. Se compara el valor a buscar x con el que se encuentra en la
posicin mitad del vector
k= n/2
2. Si x T[k] la bsqueda se restringe al subvector: T[1..k]
Si x > T[k] la bsqueda se restringe al subvector: T[k+1..n]
3. Los pasos 1 y 2 continuarn hasta:
- localizar x
- determinar que no est en el vector

Programacin III

PROBLEMA: Bsqueda binaria


funcin bsquedabin(T[1..n],x)
si n = 0 o x > T[n] entonces devolver n + 1
sino devolver binrec(T[1..n],x)
fsi
ffuncin
funcin binrec (T[i..j],x)
{Bsqueda binaria de x en la submatriz T[i..j] con la seguridad de que T[i-1] < x <= T[j]}
si i = j entonces
devolver i
fsi
k (i + j) 2
si x <= T[k] entonces devolver binrec(T[i..k],x)
sino devolver binrec(T[k + 1..j],x)
fsi
ffuncin
Programacin III

PROBLEMA: Bsqueda binaria


Coste
El tiempo requerido por busqueda_binaria () sera:
{ para aplicar las ecuaciones conocidas g(n) (nk)}
g(n) O(1) = O(m 0), k = 0
(nk)
t(n) (nk log n)
(n log b l)

si

l < bk

si

l = bk

si

l > bk

No combinamos soluciones: hay 1 caso l=1


En cada paso dividimos el tamao del problema a la mitad b = 2
l = bk { 1 = 20}
t(n) (nk log n) t(n) (log n)
Programacin III

PROBLEMA: Bsqueda binaria


Versin iterativa:
funcin biniter(T[1..n],x)
{Bsqueda binaria iterativa de x en la matriz T}
si x > T[n] entonces
devolver n + 1
fsi
i 1; j n;
mientras i < j hacer
{T[i 1] < x <= T[j]}
k (i + j) 2
si x <= T[k] entonces j k
sino i k + 1
fsi
fmientras
devolver i
ffuncin
Programacin III

PROBLEMA: Ordenacin
Sea T[1..n] una matriz de n elementos. Nuestro problema
es ordenar estos elementos por orden ascendente.
Nosotros conocemos varios mtodos de ordenacin: por
seleccin, por insercin y por montculo. ste ltimo
mtodo tiene un orden de tiempo de ( n log n).
Hay varios algoritmos clsicos de ordenacin que siguen el
esquema de divide y vencers. Nosotros vamos a estudiar
dos de ellos. Ordenar por fusin (mergesort) y ordenacin
rpida (quicksort)

Programacin III

Ordenacin por fusin


El enfoque de esta tcnica es el siguiente:
Dividir el vector en dos mitades
Ordenar esas dos mitades recursivamente
Fusionarlas en un solo vector ordenado.

Para hacer esto, necesitaremos un algoritmo eficiente para


fusionar dos matrices ordenadas U y V en una nica matriz
T cuya longitud sea la suma de las longitudes de U y V.
Programacin III

Ordenacin por fusin


procedimiento fusionar(U[1..m+1], V[1..n+1], T[1..m+n])
{Fusionar las matrices ordenadas U[1..m] y V[1..n] almacenndolas en
T[1..m+n],U[m+1] y V[n+1] se utilizan como centinelas}
i, j 1
U[m+1], V[n+1]
para k 1 hasta m+n hacer
si U[i] < V[j]
entonces T[k] U[i];
ii+1
sino T[k] V[j];
jj+1
fsi
fpara
fprocedimiento

Programacin III

Ordenacin por fusin


procedimiento ordenarporfusin (T[1..n])
si n es suficientemente pequeo entonces insertar(T)
sino
matriz U[1..1 + n / 2], V[1..1 + n / 2 ],
U[1.. n / 2] T[1.. n / 2]
V[1.. n / 2] T[1 + n / 2..n]
ordenarporfusin(U[1.. n / 2] )
ordenarporfusin(V[1.. n / 2] )
fusionar(U,V,T)
fsi
fprocedimiento
Programacin III

10

Ordenacin por fusin


Ejemplo:

Matriz que hay que ordenar


1 5 9 2 6 5 3

La matriz se divide en dos mitades


4 1 5 9
2 6 5 3 5

Una llamada recursiva a ordenar por fusin para cada mitad

Una llamada a fusionar


3 3 4 5 5 5 6

Programacin III

Ordenacin por fusin


Coste de ordenacin por fusin
El tiempo requerido por mergesort (C[n]) sera:
t(n) = t(n/2) + t(n/2) + g(n)
g(n) (nk)
t(n)

k=1

(nk)

si

l < bk

(nk log n)

si

l = bk

(n log b l)

si

l > bk

Combinamos 2 soluciones: l = 2
En cada paso dividimos el tamao del problema a la mitad b = 2
l = bk { 2 = 21}, t(n) (nk log n) t(n) (n log n)
(Est despreciando el tiempo requerido por insertar() ya que es con un n
suficientemente pequeo)
Programacin III

11

Ordenacin rpida
El primer paso es escoger un elemento de la matriz a
ordenar como pivote.
A continuacin la matriz se parte a ambos lados del
pivote. Los elementos mayores que el pivote se
almacenan a la derecha del mismo y los dems a la
izquierda.
La matriz se ordena mediante llamadas recursivas a
este algoritmo.

Programacin III

Ordenacin rpida
Uso del algoritmo
Se suele seleccionar como pivote el elemento que ocupa la
posicin central del vector o subvector a ordenar ya que:
Si todos los elementos tienen igual probabilidad, ese es tan
bueno como cualquier otro

- Si el vector est semi-ordenado u ordenado esta eleccin ser


menos costosa

Eleccin ideal del pivote


La mejor eleccin sera que el pivote fuera la mediana
mediana: dado un vector T, el elemento que tiene tantos elementos
menores como mayores que l en T

Su clculo tiene un coste lineal en el caso peor

Programacin III

12

Ordenacin rpida
procedimiento pivote (T[i..j]; var l)
{Permuta los elementos de la matriz T[i..j] y proporciona un valor l tal que, al final, i <= l <= j; T[k] <= p
para todo i <= k < l, T[l] = p, y T[k] > p para todo l< k <= j, en donde p es el valor inicial de T[i]}
p T[i]
k i; l j + 1
repetir
kk+1
hasta que T[k] > p o k >= j frepetir
repetir
ll1
hasta que T[l] <= p frepetir
mientras k < l hacer
intercambiar T[k] y T[l]
repetir
kk+1
hasta que T[k] > p frepetir
repetir
ll1
hasta que T[l] <= p frepetir
fmientras
intercambiar T[i] y T[l]
fprocedimiento

Programacin III

Ordenacin rpida
procedimiento ordenacion_rapida(T[i..j])
{Ordena la submatriz T[i..j] por orden no decreciente}
si j i es suficientemente pequeo entonces insertar (T[i..j])
sino
pivote(T[i..j],l);
ordenacion_rapida (T[i..l-1])
ordenacin_rapida (T[l+1..j])
fsi
fprocedimiento

Programacin III

13

Ordenacin rpida
Coste de ordenacin rpida
1. Si suponemos que:
el orden inicial del vector es aleatorio
los elementos de T son diferentes en su mayora
todas las n! permutaciones de sus elementos son
igualmente probables
los subproblemas estaran equilibrados
El orden sera: O(n log n)
2. Si los subproblemas no estn del todo equilibrados se suele
asumir que el coste es O(n log n)
Programacin III

Ordenacin rpida
Coste de ordenacin rpida
3. Los casos peores:
el vector est inicialmente ordenado
todos los elementos son iguales

l = i en todos los casos y se generan 2


subproblemas:
uno de tamao 0
el segundo de tamao j-i + 1

El coste sera: O(n 2)


En general se suele considerar el caso promedio: O(n log n)
Programacin III

14

Ordenacin rpida
Coste de ordenacin rpida
Si partimos de la hiptesis de que:
todos los elementos de T son diferentes
cada una de las n! permutaciones tienen la misma probabilidad
t(m) tiempo medio de ordenacion_rapida(T[i..j])
m = j - i + 1 {n de elementos en T[i..j]}
El valor l devuelto por pivote(T[1..n]) ser un entero entre 1 y n
con probabilidad 1/n

pivote(T[1..n]) requiere un tiempo g(n) (n)

El tiempo medio para ejecutar las llamadas recursivas


generadas ser:
t(l-1) + t(n -l)

Programacin III

Ordenacin rpida
Coste de ordenacin rpida
El tiempo ser por tanto:
t(n) (n) + 1/n (t(l-1) + t(n-l)) (1)
sabemos que: g(n) dn
sabemos que hay un valor k tal que 0 k n -1 que aparece 2 veces
en (1):
t(n) dn + 2/n t(k)
para n suficientemente grande
No se pueden aplicar las recurrencias lineales vistas
anteriormente
Por analoga con otros mtodos de ordenacin es razonable
esperar que : t(n) = O(n log n)
Programacin III

15

Vous aimerez peut-être aussi