Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Es un TDA contenedor de elementos del mismo tipo. Cada elemento es un par ordenado (clave, prioridad).
Las claves pueden repetirse y también las prioridades. Los elementos se almacenan de forma secuencial, como
en una cola común, pero cada nuevo elemento al ser acolado se ubica delante de aquellos de prioridad menor,
si es que hay elementos con estas características. Si no, se ubicará al final. La operación desacolar elimina el
primer elemento de la cola, al igual que en las colas habituales.
Implementaciones posibles:
Una cola con prioridades puede implementarse de múltiples formas: con arrays, con listas ligadas y también
con otras estructuras (se deja como ejercicio el planteo de los algoritmos correspondientes a las primitivas
indicadas y el análisis de los costes).
En particular nos interesa la utilización de los árboles heap o montículos para implementar el TDA cola con
prioridad, por lo que desarrollaremos ese concepto. (No confundir ”árbol heap” la zona de memoria dinámica
llamada heap).
Un árbol heap conceptualmente es un árbol binario completo o casi completo y parcialmente ordenado.
Completo significa que tiene ‘aspecto triangular’, es decir que contiene un nodo en la raíz, dos en el nivel
siguiente, y así sucesivamente teniendo todos los niveles ocupados totalmente con una cantidad de nodos que
debe ser 2.
Casi completo significa que tiene todos los niveles menos el de las hojas ‘saturados’, ocupados con
1,2,4,8,16, etc. nodos; en el nivel de las hojas puede no cumplirse esta condición, pero los nodos existentes
deben estar ubicados ‘a izquierda’.
Ejemplo:
‘Parcialmente ordenado’ significa que para todo nodo se cumple que los valores de sus nodos hijos (si los
tuviera) son ambos menores o iguales que el del nodo padre (árbol heap de máximo), o bien que para todo
pág. 1
Colas de Prioridad y árbol heap. Curso P Calvo, 2017
nodo se cumple que los valores de sus hijos son ambos mayores o iguales que los de su nodo padre (y se llama
árbol heap de mínimo). Entre los hijos no se exige ningún orden en particular.
Ejemplo:
Es muy frecuente que un árbol heap se implemente con un array, almacenando los valores por nivel, del
siguiente modo:
2 10 8 15 12 11 13 30 27 29
Considerando que las posiciones del array son 0, 1, ...n-1, se verifica que las posiciones de los nodos hijos con
respecto a su nodo padre cumplen :
Análogamente, si el hijo está en posición h, su padre estará en posición (h-1)/2 , considerando cociente entero.
a) Extraer raíz:
Se reemplaza 2 por 29
Se elimina el nodo hoja con 29.
Luego se debe restaurar el árbol heap.
El menor de los hijos es 8, que es Ahora el problema se analiza para el Árbol heap restaurado
menor que 29, por lo cual se nodo con 29 y sus hijos, 11 y 13.
intercambia con él 29 se intercambia con 11
pág. 2
Colas de Prioridad y árbol heap. Curso P Calvo, 2017
2 10 8 15 12 11 13 30 27 29
29 10 8 15 12 11 13 30 27 29
29 10 8 15 12 11 13 30 27 29
Se compara 29 con sus hijos (la posición se determina como se indicó antes)
8 10 29 15 12 11 13 30 27 29
8 10 29 15 12 11 13 30 27 29
8 10 29 15 12 11 13 30 27 29
8 10 11 15 12 29 13 30 27 29
El nuevo elemento se ubica como ‘última hoja’. Luego se restaura el montículo analizando ternas ‘hacia
arriba’ hasta ubicar el nuevo elemento en su posición definitiva:
Ejemplo:
8 10 11 15 12 29 13 30 27 9
Se almacena 9 como nueva hoja, es decir, se pone a continuación del último valor almacenado en el array. De
esta forma, N, número de elementos del array, pasa de 9 a 10.
8 10 11 15 12 29 13 30 27 9
8 10 11 15 9 29 13 30 27 12
pág. 4
Colas de Prioridad y árbol heap. Curso P Calvo, 2017
8 10 11 15 9 29 13 30 27 12
8 9 11 15 10 29 13 30 27 12
8 9 11 15 10 29 13 30 27 12
Se analiza la situación de 9 con respecto a 8; como se verifica la condición del heap, no se realiza intercambio,
y el proceso concluye.
8 9 11 15 10 29 13 30 27 12
Coste de la operación:
Considerando una implementación en array, el agregado de una nueva hoja es de coste constante, ya que se
agrega un elemento a continuación del último almacenado en el array. Como sucedió en el caso de la
extracción de la raíz, al agregar un nuevo elemento, se realizan comparaciones (una en esta operación) y un
eventual intercambio desde el nivel de las hojas hasta el nivel de la raíz. En el peor caso, se realizará esto
tantas veces como niveles tenga el árbol heap, menos uno. Es decir que, considerando que la altura del árbol
es aproximadamente log2 N, el coste es O(log N).
El alta de un elemento en el heap permite implementar la primitiva Acolar de la cola con prioridades.
La baja de la raíz en el árbol heap permite implementar la primitiva Desacolar de la cola con prioridades.
En la primera parte se convierte el array en un montículo, reubicando los elementos del mismo.
En la segunda parte, en sucesivas etapas intercambia el elemento de la raíz con la última hoja, decrementa la
posición considerada última del array y recompone el montículo desde la primera posición del array (posición
de la raíz) hasta la última considerada.
Observar que si se quiere ordenar el array de modo ascendente, el montículo debe verificar que el valor de
cada nodo debe ser mayor que el de sus hijos, y lo contrario para un ordenamiento descendente.
pág. 5
Colas de Prioridad y árbol heap. Curso P Calvo, 2017
{
// se intercambia el valor de la raíz con el de la última hoja
swap(arr[0], arr[i]);
// si el mayor no es raíz
if (largest != i)
{
swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}
Como hemos dicho, el ordenamiento heapsort tiene dos etapas: en la primera se construye un heap sobre el
array. En la segunda etapa, mientras la zona del heap sea mayor que 1, se intercambia el valor de la raíz con la
última hoja (si se tiene un heap de máximo, esto manda dicho elemento al final de la zona del heap), se reduce
la zona del heap en 1 (con lo cual no se toca la posición del elemento que antes estaba en la raíz) y se restaura
el heap desde la primera posición hasta la última de la zona, es decir, se reubica en el lugar correcto la clave
que se ha colocado como raíz.
La primera etapa, a primera vista puede llevarnos a la conclusión de que pertenece a O(n * log n), lo cual no
está mal, pero se puede obtener un O más ajustado si consideramos que en la construcción del heap, cuando se
llama a heapify, el número de pasos (comparaciones e intercambios) depende de hasta dónde cada elemento
debe moverse hacia abajo en el heap. En el peor caso, el elemento podría bajar hasta el nivel de la hoja; el
número de pasos depende del número de niveles del árbol.
Ahora bien, si el árbol tiene t niveles, en el nivel más bajo, hay 2t-1 nodos, pero no se llamamos a heapify para
ninguno de ellos. En el siguiente nivel hay 2t-2 nodos, y cada uno podría moverse hacia abajo 1 nivel. En el
tercer nivel (contando siempre desde abajo), hay 2t-3 nodos, y cada uno puede bajar 2 niveles. Haciendo la
sumatoria correspondiente (se deja la última parte del cálculo como ejercicio) obtenemos que la construcción
del heap pertenece a O (n), siendo n el número de nodos del árbol.
En la segunda etapa, mientras el heap no esté vacío (es decir un número de veces que es O(n)) se realiza un
intercambio entre la raíz y la última hoja, se reduce en 1 el tamaño del heap (todo esto de coste constante) y se
restaura nuevamente el heap (lo cual puede tener un coste O(log n)). Por tanto esta segunda etapa pertenece a
O(n*log n).
pág. 6
Colas de Prioridad y árbol heap. Curso P Calvo, 2017
Por la regla de la suma, O(n) +O(n*log n) es O(n * log n), que es el coste del Heapsort.
Ejemplo:
3 2 1 9 7 6
3 2 6 9 7 1
3 9 6 2 7 1
9 3 6 2 7 1
9 7 6 2 3 1
1 7 6 2 3 9
7 1 6 2 3 9
7 3 6 2 1 9
1 3 6 2 7 9
6 3 1 2 7 9
2 3 1 6 7 9
3 2 1 6 7 9
1 2 3 6 7 9
2 1 3 6 7 9
pág. 7
Colas de Prioridad y árbol heap. Curso P Calvo, 2017
1 2 1 6 7 9
Ejercicios:
1) Desarrollar un algoritmo Fusión, que a partir de dos montículos del mismo tipo genere uno nuevo del
mismo tipo. ¿cuál es el menor coste de un algoritmo que realice esa tarea?
2) Desarrollar un algoritmo Modificar_clave que permita modificar la prioridad de un elemento del
montículo y restaurar el mismo. ¿cuál es el coste?
pág. 8