Monticulos y PD
Monticulos y PD
Monticulos y PD
Algoritmos
Julián Rosero
Cristian Pujota
José Pillajo
Algoritmos
MONTÍCULOS
Un montículo es un árbol binario en el que los valores de cada nodo son menores o igual que los valores de sus
hijos, es decir ningún padre tiene un hijo mayor o menor a él. Ejemplo:
56
37 48
Universidad Central del Ecuador
5 7 14
Como observamos el ejemplo es un montículo binario ya que ningún nodo padre tiene un hijo con un valor
mayor que él.
min-heap : el valor de cada nodo es mayor o igual que el valor de su padre, con el elemento de
valor mínimo en la raíz.
max-heap : el valor de cada nodo es menor o igual que el valor de su padre, con el elemento de
valor máximo en la raíz.
- USOS DE MONTÍCULOS
2
Algoritmos
Una estructura de montículo tiene aplicaciones importantes en otros algoritmos conocidos:
polinómico.
- IMPLEMENTACIÓN DE MONTÍCULOS
elementos:
1) Un vector T[1..n].
2) Un contador e para el número de elementos del montículo.
3) Un valor para el tamaño máximo del montículo.
Flotar: reubica el elemento i-esimo del vector en caso de que este sea mayor que el
Hundir: reubica el elemento i-esimo del vector en caso de que éste sea menor que alguno de sus hijos.
En tal caso, intercambia su valor por el del mayor de sus hijos (montículo de máximos).
montículo.
2
Algoritmos
Aplicaremos el algoritmo de ordenamiento por montículo el cual recorre el conjunto de elementos
desde la posición de la mitad hasta la primera organizando el montículo correspondiente a dicho
elemento. Una vez terminado este proceso, se inicia el proceso de ordenación intercambiando el primer
elemento por el último del arreglo y reorganizando el montículo a partir de la primera posición.
v[0] = v[nodo];
v[nodo] = tmp;
hacerMonticulo(v, 0, nodo-1);
}
Universidad Central del Ecuador
public static void hacerMonticulo(int[] v, int nodo, int fin) {
int may;
if(izq>fin) return;
if(der>fin) may=izq;
v[nodo] = v[may];
v[may] = tmp;
2
Algoritmos
La complejidad del algoritmo de ordenación por montículos es O(n log n) teniendo en cuenta que el
proceso de organizar el montículo en el peor caso solamente tiene que hacer intercambios sobre una sola
línea de elementos desde la raíz del árbol hasta alguna de las hojas para un máximo de log n intercambios.
PROGRAMACIÓN DINÁMICA
La programación dinámica es la técnica de diseño más potente para resolver problemas de optimización.
La programación dinámica se utiliza cuando los subproblemas no son independientes, por ejemplo, cuando
comparten los mismos subproblemas. En este caso, el algoritmo divide y vencerás puede hacer más trabajo
del necesario, ya que resuelve el mismo subproblema varias veces.
Para un mejor entendimiento del problema tenemos el ejemplo del algoritmo de Fibonacci tratado con el
método divide y vencerás.
Fib(2) Fib(1)
- ¿CUÁNDO FUNCIONA?
2
Algoritmos
La programación dinámica
funciona cuando un problema
tiene las siguientes
características:
Subestructura óptima: si una
solución óptima contiene sub
soluciones óptimas, entonces
un problema exhibe una
subestructura óptima.
Subp
(Imagen tomada de: “ https://www.ifsworld.com”)
roblemas superpuestos: cuando un algoritmo recursivo
visitaría los mismos subproblemas repetidamente, entonces
un problema tiene subproblemas superpuestos.
Si un problema tiene una subestructura óptima, entonces podemos definir recursivamente una
solución óptima. Si un problema tiene subproblemas que se superponen, entonces podemos
mejorar una implementación recursiva calculando cada subproblema solo una vez.
Si un problema no tiene una subestructura óptima, no hay una base para definir un algoritmo
Universidad Central del Ecuador
recursivo para encontrar las soluciones óptimas. Si un problema no tiene subproblemas
superpuestos, no tenemos nada que ganar al usar la programación dinámica.
Si el espacio de los subproblemas es suficiente (es decir, polinomio en el tamaño de la entrada), la
programación dinámica puede ser mucho más eficiente que la recursión.
- EJEMPLO EN JAVA
La intuición detrás de la programación dinámica es que cambiamos espacio por tiempo, es decir,
para decir que en lugar de calcular todos los estados que toman mucho tiempo, pero sin espacio,
tomamos espacio para almacenar los resultados de todos los subproblemas para ahorrar tiempo
más tarde.
Fibonacci (n) = 1; si n = 0
Fibonacci (n) = 1; si n = 1
Fibonacci (n) = Fibonacci (n-1) + Fibonacci (n-2)
2
Algoritmos
Entonces, los primeros números de esta serie serán: 1, 1, 2, 3, 5, 8, 13, 21 ... ¡ y así sucesivamente!
Usando
el
void fib () {
fibresult[0] = 1;
fibresult[1] = 1;
for (int i = 2; i<n; i++)
fibresult[i] = fibresult[i-1] + fibresult[i-2];
}
- CONCLUSIÓN
La programación dinámica es una herramienta que nos puede ahorrar una gran cantidad de tiempo
de cómputo a cambio de una mayor complejidad de espacio, ya que algunos de ellos solo van a la
mitad (se necesita una matriz para la memorización, pero se utiliza una matriz en constante cambio).
Esto depende en gran medida del tipo de sistema en el que esté trabajando; si el tiempo de CPU es
valioso, opta por una solución que consuma memoria; por otra parte, si su memoria es limitada, opta
por una solución más lenta para una mejor relación tiempo / espacio de complejidad.
2
Algoritmos