SlideShare una empresa de Scribd logo
1 de 33
Descargar para leer sin conexión
Algorítmica: Heaps y heapsort
Conrado Martínez
U. Politècnica Catalunya
Q1-2011-2012
Una cola de prioridad (cat: cua de prioritat; ing: priority queue)
es una colección de elementos donde cada elemento tiene
asociado un valor susceptible de ordenación denominado
prioridad.
Una cola de prioridad se caracteriza por admitir inserciones de
nuevos elementos y la consulta y eliminación del elemento de
mínima (o máxima) prioridad.
template <typename Elem, typename Prio>
class ColaPrioridad {
public:
...
// Añade el elemento x con prioridad p a la cola de
// prioridad.
void inserta(cons Elem& x, const Prio& p) throw(error)
// Devuelve un elemento de mínima prioridad en la cola de
// prioridad. Se lanza un error si la cola está vacía.
Elem min() const throw(error);
// Devuelve la mínima prioridad presente en la cola de
// prioridad. Se lanza un error si la cola está vacía.
Prio prio_min() const throw(error);
// Elimina un elemento de mínima prioridad de la cola de
// prioridad. Se lanza un error si la cola está vacía.
void elim_min() throw(error);
// Devuelve cierto si y sólo si la cola está vacía.
bool vacia() const throw();
};
// Tenemos dos arrays Peso y Simb con los pesos atómicos
// y símbolos de n elementos químicos,
// p.e., Simb[i] = "C" y Peso[i] = 12.2.
// Utilizamos una cola de prioridad para ordenar la
// información de menor a mayor símbolo en orden alfabético
ColaPrioridad<double, string> P;
for (int i = 0; i < n; ++i)
P.inserta(Peso[i], Simb[i]);
int i = 0;
while(! P.vacia()) {
Peso[i] = P.min();
Simb[i] = P.prio_min();
++i;
P.elim_min();
}
Se puede usar una cola de prioridad para hallar el k-ésimo
elemento de un vector no ordenado. Se colocan los k primeros
elementos del vector en una max-cola de prioridad y a
continuación se recorre el resto del vector, actualizando la cola
de prioridad cada vez que el elemento es menor que el mayor
de los elementos de la cola, eliminando al máximo e insertando
el elemento en curso.
Muchas de las técnicas empleadas para la implementación
de diccionarios puede usarse para implementar colas de
prioridad (no las tablas de hash ni los tries)
P.e., con árboles binarios de búsqueda equilibrados se
puede conseguir coste y@lognA para inserciones y
eliminaciones
Definición
Un montículo (ing: heap) es un árbol binario tal que
1 todos las hojas (subárboles son vacíos) se sitúan en los
dos últimos niveles del árbol.
2 en el antepenúltimo nivel existe a lo sumo un nodo interno
con un sólo hijo, que será su hijo izquierdo, y todos los
nodos a su derecha en el mismo nivel son nodos internos
sin hijos.
3 el elemento (su prioridad) almacenado en un nodo
cualquiera es mayor (menor) o igual que los elementos
almacenados en sus hijos izquierdo y derecho.
Se dice que un montículo es un árbol binario quasi-completo
debido a las propiedades 1-2. La propiedad 3 se denomina
orden de montículo, y se habla de max-heaps o min-heaps
según que los elementos sean ! ó que sus hijos.
Proposición
1 El elemento máximo de un max-heap se encuentra en la
raíz.
2 Un heap de n elementos tiene altura
h a dlog2@n CIAe:
La consulta del máximo es sencilla y eficiente pues basta
examinar la raíz.
Cómo eliminar el máximo?
1 Ubicar al último elemento del montículo (el del último nivel
más a la derecha) en la raíz, sustituyendo al máximo
2 Reestablecer el invariante (orden de heap) hundiendo la
raíz.
El método hundir intercambia un nodo dado con el mayor de
sus dos hijos si el nodo es menor que alguno de ellos, y repete
este paso hasta que el invariante de heap se ha reestablecido
Cómo añadir un nuevo elemento?
1 Colocar el nuevo elemento como último elemento del
montículo, justo a la derecha del último o como primero de
un nuevo nivel
2 Reestablecer el orden de montıculo flotando el elemento
recién añadido
En el método flotar el nodo dado se compara con su nodo
padre y se realiza el intercambio si éste es mayor que el padre,
iterando este paso mientras sea necesario
Puesto que la altura del heap es ¢@lognA el coste de
inserciones y eliminaciones será y@lognA.
Se puede implementar un heap mediante memoria dinámica,
con apuntadores al hijo izquierdo y derecho y también al padre
en cada nodo
Pero es mucho más fácil y eficiente implementar los heaps
mediante un vector. No se desperdicia demasiado espacio ya
que el heap es quasi-completo; en caso necesario puede
usarse el redimensionado
Reglas para representar un heap en vector:
1 A‘I“ contiene la raíz.
2 Si Pi n entonces A‘Pi“ contiene al hijo izquierdo del
elemento en A‘i“ y si Pi CI n entonces A‘Pi CI“
contiene al hijo derecho de A‘i“
3 Si i ! P entonces A‘i=P“ contiene al padre de A‘i“
Las reglas anteriores implican que los elementos del heap se
ubican en posiciones consecutivas del vector, colocando la raíz
en la primera posición y recorriendo el árbol por niveles, de
izquierda a derecha.
template <typename Elem, typename Prio>
class ColaPrioridad {
public:
...
private:
// la componente 0 no se usa; el constructor de la clase
// inserta un elemento ficticio
vector<pair<Elem, Prio> > h;
int nelems;
void flotar(int j) throw();
void hundir(int j) throw();
};
template <typename Elem, typename Prio>
bool ColaPrioridad<Elem,Prio>::vacia() const throw() {
return nelems == 0;
}
template <typename Elem, typename Prio>
Elem ColaPrioridad<Elem,Prio>::min() const throw(error) {
if (nelems == 0) throw error(ColaVacia);
return h[1].first;
}
template <typename Elem, typename Prio>
Prio ColaPrioridad<Elem,Prio>::prio_min() const throw(error) {
if (nelems == 0) throw error(ColaVacia);
return h[1].second;
}
template <typename Elem, typename Prio>
void ColaPrioridad<Elem,Prio>::inserta(cons Elem& x,
cons Prio& p) throw(error) {
++nelems;
h.push_back(make_pair(x, p));
flotar(nelems);
}
template <typename Elem, typename Prio>
void ColaPrioridad<Elem,Prio>::elim_min() const throw(error) {
if (nelems == 0) throw error(ColaVacia);
swap(h[1], h[nelems]);
--nelems;
hundir(1);
}
// Versión recursiva.
// Hunde el elemento en la posición j del heap
// hasta reestablecer el orden del heap; por
// hipótesis los subárboles del nodo j son heaps.
// Coste: O(log(n/j))
template <typename Elem, typename Prio>
void ColaPrioridad<Elem,Prio>::hundir(int j) throw() {
// si j no tiene hijo izquierdo, hemos terminado
if (2 * j > nelems) return;
int minhijo = 2 * j;
if (minhijo < nelems &&
h[minhijo].second > h[minhijo + 1].second)
++minhijo;
// minhijo apunta al hijo de minima prioridad de j
// si la prioridad de j es mayor que la de su menor hijo
// intercambiar y seguir hundiendo
if (h[j].second > h[minhijo].second) {
swap(h[j], h[minhijo]);
hundir(minhijo);
}
}
// Versión iterativa.
// Hunde el elemento en la posición j del heap
// hasta reestablecer el orden del heap; por
// hipótesis los subárboles del nodo j son heaps.
// Coste: O(log(n/j))
template <typename Elem, typename Prio>
void ColaPrioridad<Elem,Prio>::hundir(int j) throw() {
bool fin = false;
while (2 * j <= nelems && !fin) {
int minhijo = 2 * j;
if (minhijo < nelems &&
h[minhijo].second > h[minhijo + 1].second)
++minhijo;
if (h[j].second > h[minhijo].second) {
swap(h[j], h[minhijo]);
j = minhijo;
} else {
fin = true;
}
}
}
// Flota al nodo j hasta reestablecer el orden del heap;
// todos los nodos excepto el j satisfacen la propiedad
// de heap
// Coste: O(log j)
template <typename Elem, typename Prio>
void ColaPrioridad<Elem,Prio>::flotar(int j) throw() {
// si j es la raíz, hemos terminado
if (j == 1) return;
int padre = j / 2;
// si el padre tiene mayor prioridad
// que j, intercambiar y seguir flotando
if (h[j].second < h[padre].second) {
swap(h[j], h[padre]);
flotar(padre);
}
}
Heapsort
Heapsort (Williams, 1964) ordena un vector de n elementos
construyendo un heap con los n elementos y extrayéndolos,
uno a uno del heap a continuación. El propio vector que
almacena a los n elementos se emplea para construir el heap,
de modo que heapsort actúa in-situ y sólo requiere un espacio
auxiliar de memoria constante. El coste de este algoritmo es
¢@n lognA (incluso en caso mejor) si todos los elementos son
diferentes.
En la práctica su coste es superior al de quicksort, ya que el
factor constante multiplicativo del término n logn es mayor.
// Ordena el vector v[1..n]
// (v[0] no se usa)
// de Elem’s de menor a mayor
template <typename Elem>
void heapsort(Elem v[], int n) {
crea_max_heap(v, n);
for (int i = n; i > 0; --i) {
// saca el mayor elemento del heap
swap(v[1], v[i]);
// hunde el elemento de indice 1
// para reestablecer un max-heap en
// el subvector v[1..i-1]
hundir(v, i-1, 1);
}
}
// Da estructura de max-heap al
// vector v[1..n] de Elem’s; aquí
// cada elemento se identifica con su
// prioridad
template <typename Elem>
void crea_max_heap(Elem v[], int n) {
for (int i = n/2; i > 0; --i)
hundir(v, n, i);
}
Sea H@nA el coste en caso peor de heapsort y B@nA el coste
de crear el heap inicial. El coste en caso peor de
hundir@v; i  I; IA es y@logiA y por lo tanto
H@nA a B@nAC
i=nX
i=1
y@logiA
a B@nACy
0
@
X
1 i n
log2 i
1
A
a B@nACy@log@n3AA a B@nACy@n lognA
Un análisis simple de B@nA indica que B@nA a y@n lognA ya
que hay ¢@nA llamadas a hundir, cada una de las cuales
tiene coste y@lognA
Por tanto H@nA a y@n lognA, de hecho H@nA a ¢@n lognA en
caso peor
Podemos refinar el análisis de B@nA:
B@nA a
X
1 i ˜n=2™
y@log@n=iAA
a y log n
n=2
@n=PA3
!
a y

log@PeAn=2

a y@nA
Puesto que B@nA a @nA, podemos afirmar que B@nA a ¢@nA.
Demostración alternativa: Sea h a dlog2@n CIAe la altura del
heap. En el nivel h  I k hay como mucho
Ph 1 k

n CI
Pk
nodos y cada uno de ellos habrá de hundirse en caso peor
hasta el nivel h  I; eso tiene coste y@kA
Por lo tanto,
B@nA a
X
0 k h 1
y@kAn CI
Pk
a y
0
@n
X
0 k h 1
k
Pk
1
A
a y
0
@n
X
k!0
k
Pk
1
A a y@nA;
ya que
X
k!0
k
Pk
a P:
En general, si jrj  I,
X
k!0
k ¡r
k
a r
@I rA2
:
Aunque H@nA a ¢@n lognA, el análisis detallado de B@nA es
importante: utilizando un min-heap podemos hallar los k
menores elementos en orden creciente de un vector (y en
particular el k-ésimo) con coste:
S@n; kA a B@nACk ¡y@lognA
a y@n Ck lognA:
y si k a y@n= lognA entonces S@n; kA a y@nA.

Más contenido relacionado

La actualidad más candente

P R A C T I C A2
P R A C T I C A2P R A C T I C A2
P R A C T I C A2climancc
 
Java ArrayList Iterator
Java ArrayList IteratorJava ArrayList Iterator
Java ArrayList Iteratorjubacalo
 
2. Manejo de la sintaxis del lenguaje
2. Manejo de la sintaxis del lenguaje2. Manejo de la sintaxis del lenguaje
2. Manejo de la sintaxis del lenguajeLaura Folgado Galache
 
Java::Acceso a Bases de Datos
Java::Acceso a Bases de DatosJava::Acceso a Bases de Datos
Java::Acceso a Bases de Datosjubacalo
 
6. Utilización del modelo de objetos del documento (DOM)
6. Utilización del modelo de objetos del documento (DOM)6. Utilización del modelo de objetos del documento (DOM)
6. Utilización del modelo de objetos del documento (DOM)Laura Folgado Galache
 
Jyoc java-cap20 listas, colas y pilas
Jyoc java-cap20 listas, colas y pilasJyoc java-cap20 listas, colas y pilas
Jyoc java-cap20 listas, colas y pilasJyoc X
 
Java HashMap
Java HashMapJava HashMap
Java HashMapjubacalo
 
Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...
Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...
Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...David Zapateria Besteiro
 
Clase3 asignaciones
Clase3 asignacionesClase3 asignaciones
Clase3 asignacionesjorg_marq
 
Sincronizar Threads
Sincronizar ThreadsSincronizar Threads
Sincronizar Threadsjubacalo
 
Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...
Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...
Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...David Zapateria Besteiro
 
Entrega de reporte no 1, lab 1
Entrega de reporte no 1, lab 1Entrega de reporte no 1, lab 1
Entrega de reporte no 1, lab 1Antares Zehcnas
 

La actualidad más candente (18)

P R A C T I C A2
P R A C T I C A2P R A C T I C A2
P R A C T I C A2
 
C++
C++C++
C++
 
Programación en c++
Programación en c++Programación en c++
Programación en c++
 
Java ArrayList Iterator
Java ArrayList IteratorJava ArrayList Iterator
Java ArrayList Iterator
 
2. Manejo de la sintaxis del lenguaje
2. Manejo de la sintaxis del lenguaje2. Manejo de la sintaxis del lenguaje
2. Manejo de la sintaxis del lenguaje
 
Java::Acceso a Bases de Datos
Java::Acceso a Bases de DatosJava::Acceso a Bases de Datos
Java::Acceso a Bases de Datos
 
Taller Matrices En Java
Taller Matrices En JavaTaller Matrices En Java
Taller Matrices En Java
 
6. Utilización del modelo de objetos del documento (DOM)
6. Utilización del modelo de objetos del documento (DOM)6. Utilización del modelo de objetos del documento (DOM)
6. Utilización del modelo de objetos del documento (DOM)
 
C++ y sus librerias
C++ y sus libreriasC++ y sus librerias
C++ y sus librerias
 
Jyoc java-cap20 listas, colas y pilas
Jyoc java-cap20 listas, colas y pilasJyoc java-cap20 listas, colas y pilas
Jyoc java-cap20 listas, colas y pilas
 
Java HashMap
Java HashMapJava HashMap
Java HashMap
 
Por qué java no soporta la sobre carga de operadores
Por qué java no soporta la sobre carga de operadoresPor qué java no soporta la sobre carga de operadores
Por qué java no soporta la sobre carga de operadores
 
Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...
Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...
Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...
 
Clase3 asignaciones
Clase3 asignacionesClase3 asignaciones
Clase3 asignaciones
 
Sincronizar Threads
Sincronizar ThreadsSincronizar Threads
Sincronizar Threads
 
Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...
Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...
Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...
 
Entrega de reporte no 1, lab 1
Entrega de reporte no 1, lab 1Entrega de reporte no 1, lab 1
Entrega de reporte no 1, lab 1
 
Clase2_Python-CTIC
Clase2_Python-CTICClase2_Python-CTIC
Clase2_Python-CTIC
 

Destacado

estrategia de facilitamiento
estrategia de facilitamientoestrategia de facilitamiento
estrategia de facilitamientonaguirre123
 
Presentación Inicial TIC
Presentación Inicial TICPresentación Inicial TIC
Presentación Inicial TICIsrael Casas
 
Sistema monetario
Sistema monetarioSistema monetario
Sistema monetariosolotavalo
 
Como insertar imagen a un blogger
Como insertar imagen a un bloggerComo insertar imagen a un blogger
Como insertar imagen a un bloggeresmeraldaaraya
 
trabajo en clase
trabajo en clasetrabajo en clase
trabajo en claseesilvalesme
 
Manual crowd(gutiérrez rubí & freire, 2013)
Manual crowd(gutiérrez rubí & freire, 2013)Manual crowd(gutiérrez rubí & freire, 2013)
Manual crowd(gutiérrez rubí & freire, 2013)Pablo Mella Donoso
 
Mood board
Mood boardMood board
Mood boardJaket123
 
social media e movimenti _ lezione Istituto Piemontese Per La Storia Della Re...
social media e movimenti _ lezione Istituto Piemontese Per La Storia Della Re...social media e movimenti _ lezione Istituto Piemontese Per La Storia Della Re...
social media e movimenti _ lezione Istituto Piemontese Per La Storia Della Re...Bertram Niessen
 
Somos uno
Somos unoSomos uno
Somos unokadirth
 
Trabajo de reciclaje 4ºB
Trabajo de reciclaje 4ºBTrabajo de reciclaje 4ºB
Trabajo de reciclaje 4ºBjavivi234
 
Trabajo de Plan Ciencias. version Beta
Trabajo de Plan Ciencias. version BetaTrabajo de Plan Ciencias. version Beta
Trabajo de Plan Ciencias. version BetaRodrigoCordero8
 
Trabajo de reflexión. Ailen Garcia
Trabajo de reflexión. Ailen GarciaTrabajo de reflexión. Ailen Garcia
Trabajo de reflexión. Ailen GarciaLasangelesdePablo
 

Destacado (20)

estrategia de facilitamiento
estrategia de facilitamientoestrategia de facilitamiento
estrategia de facilitamiento
 
Presentación Inicial TIC
Presentación Inicial TICPresentación Inicial TIC
Presentación Inicial TIC
 
Lenguaje
LenguajeLenguaje
Lenguaje
 
Correcto
CorrectoCorrecto
Correcto
 
slidecast
slidecastslidecast
slidecast
 
Ya se va?
Ya se va?Ya se va?
Ya se va?
 
Sistema monetario
Sistema monetarioSistema monetario
Sistema monetario
 
Como insertar imagen a un blogger
Como insertar imagen a un bloggerComo insertar imagen a un blogger
Como insertar imagen a un blogger
 
trabajo en clase
trabajo en clasetrabajo en clase
trabajo en clase
 
Manual crowd(gutiérrez rubí & freire, 2013)
Manual crowd(gutiérrez rubí & freire, 2013)Manual crowd(gutiérrez rubí & freire, 2013)
Manual crowd(gutiérrez rubí & freire, 2013)
 
Mood board
Mood boardMood board
Mood board
 
Internet
InternetInternet
Internet
 
Recuperacion 1
Recuperacion 1Recuperacion 1
Recuperacion 1
 
Tarea 2
Tarea 2Tarea 2
Tarea 2
 
social media e movimenti _ lezione Istituto Piemontese Per La Storia Della Re...
social media e movimenti _ lezione Istituto Piemontese Per La Storia Della Re...social media e movimenti _ lezione Istituto Piemontese Per La Storia Della Re...
social media e movimenti _ lezione Istituto Piemontese Per La Storia Della Re...
 
Somos uno
Somos unoSomos uno
Somos uno
 
Trabajo de reciclaje 4ºB
Trabajo de reciclaje 4ºBTrabajo de reciclaje 4ºB
Trabajo de reciclaje 4ºB
 
Trabajo de Plan Ciencias. version Beta
Trabajo de Plan Ciencias. version BetaTrabajo de Plan Ciencias. version Beta
Trabajo de Plan Ciencias. version Beta
 
Trabajo de reflexión. Ailen Garcia
Trabajo de reflexión. Ailen GarciaTrabajo de reflexión. Ailen Garcia
Trabajo de reflexión. Ailen Garcia
 
Portada
PortadaPortada
Portada
 

Similar a Pqueues

Similar a Pqueues (20)

Estructura datos pilas y colas
Estructura datos pilas y colasEstructura datos pilas y colas
Estructura datos pilas y colas
 
Estructuradatospilasycolas 121106170754-phpapp02
Estructuradatospilasycolas 121106170754-phpapp02Estructuradatospilasycolas 121106170754-phpapp02
Estructuradatospilasycolas 121106170754-phpapp02
 
Estructura de datos pilas y colas
Estructura de datos pilas y colasEstructura de datos pilas y colas
Estructura de datos pilas y colas
 
Pilas
PilasPilas
Pilas
 
Pilas y Colas
Pilas y ColasPilas y Colas
Pilas y Colas
 
Colas
ColasColas
Colas
 
6-Pilas.pdf
6-Pilas.pdf6-Pilas.pdf
6-Pilas.pdf
 
13 heaps
13 heaps13 heaps
13 heaps
 
HEAPS
HEAPSHEAPS
HEAPS
 
Lista Doblemente Enlazada
Lista Doblemente EnlazadaLista Doblemente Enlazada
Lista Doblemente Enlazada
 
Heaps
HeapsHeaps
Heaps
 
Introduccion a C++
Introduccion a C++Introduccion a C++
Introduccion a C++
 
Listas cola y_pila.ranli_y_eladio
Listas cola y_pila.ranli_y_eladioListas cola y_pila.ranli_y_eladio
Listas cola y_pila.ranli_y_eladio
 
2- TDA Listas
2- TDA Listas2- TDA Listas
2- TDA Listas
 
Listas pilascolas edward.mejia-10-1314
Listas pilascolas edward.mejia-10-1314Listas pilascolas edward.mejia-10-1314
Listas pilascolas edward.mejia-10-1314
 
Listas Pilas Colas
Listas Pilas ColasListas Pilas Colas
Listas Pilas Colas
 
Pilas En C++
Pilas En C++Pilas En C++
Pilas En C++
 
Estructura de datos I Primera Parte
Estructura de datos I Primera ParteEstructura de datos I Primera Parte
Estructura de datos I Primera Parte
 
Ejercicios evaluados i. shearly achji y ricardo ros. estructuras de datos i. ...
Ejercicios evaluados i. shearly achji y ricardo ros. estructuras de datos i. ...Ejercicios evaluados i. shearly achji y ricardo ros. estructuras de datos i. ...
Ejercicios evaluados i. shearly achji y ricardo ros. estructuras de datos i. ...
 
Metodos De Ordenamiento
Metodos De OrdenamientoMetodos De Ordenamiento
Metodos De Ordenamiento
 

Pqueues

  • 1. Algorítmica: Heaps y heapsort Conrado Martínez U. Politècnica Catalunya Q1-2011-2012
  • 2. Una cola de prioridad (cat: cua de prioritat; ing: priority queue) es una colección de elementos donde cada elemento tiene asociado un valor susceptible de ordenación denominado prioridad. Una cola de prioridad se caracteriza por admitir inserciones de nuevos elementos y la consulta y eliminación del elemento de mínima (o máxima) prioridad.
  • 3. template <typename Elem, typename Prio> class ColaPrioridad { public: ... // Añade el elemento x con prioridad p a la cola de // prioridad. void inserta(cons Elem& x, const Prio& p) throw(error) // Devuelve un elemento de mínima prioridad en la cola de // prioridad. Se lanza un error si la cola está vacía. Elem min() const throw(error); // Devuelve la mínima prioridad presente en la cola de // prioridad. Se lanza un error si la cola está vacía. Prio prio_min() const throw(error); // Elimina un elemento de mínima prioridad de la cola de // prioridad. Se lanza un error si la cola está vacía. void elim_min() throw(error); // Devuelve cierto si y sólo si la cola está vacía. bool vacia() const throw(); };
  • 4. // Tenemos dos arrays Peso y Simb con los pesos atómicos // y símbolos de n elementos químicos, // p.e., Simb[i] = "C" y Peso[i] = 12.2. // Utilizamos una cola de prioridad para ordenar la // información de menor a mayor símbolo en orden alfabético ColaPrioridad<double, string> P; for (int i = 0; i < n; ++i) P.inserta(Peso[i], Simb[i]); int i = 0; while(! P.vacia()) { Peso[i] = P.min(); Simb[i] = P.prio_min(); ++i; P.elim_min(); }
  • 5. Se puede usar una cola de prioridad para hallar el k-ésimo elemento de un vector no ordenado. Se colocan los k primeros elementos del vector en una max-cola de prioridad y a continuación se recorre el resto del vector, actualizando la cola de prioridad cada vez que el elemento es menor que el mayor de los elementos de la cola, eliminando al máximo e insertando el elemento en curso.
  • 6. Muchas de las técnicas empleadas para la implementación de diccionarios puede usarse para implementar colas de prioridad (no las tablas de hash ni los tries) P.e., con árboles binarios de búsqueda equilibrados se puede conseguir coste y@lognA para inserciones y eliminaciones
  • 7. Definición Un montículo (ing: heap) es un árbol binario tal que 1 todos las hojas (subárboles son vacíos) se sitúan en los dos últimos niveles del árbol. 2 en el antepenúltimo nivel existe a lo sumo un nodo interno con un sólo hijo, que será su hijo izquierdo, y todos los nodos a su derecha en el mismo nivel son nodos internos sin hijos. 3 el elemento (su prioridad) almacenado en un nodo cualquiera es mayor (menor) o igual que los elementos almacenados en sus hijos izquierdo y derecho.
  • 8. Se dice que un montículo es un árbol binario quasi-completo debido a las propiedades 1-2. La propiedad 3 se denomina orden de montículo, y se habla de max-heaps o min-heaps según que los elementos sean ! ó que sus hijos.
  • 9.
  • 10. Proposición 1 El elemento máximo de un max-heap se encuentra en la raíz. 2 Un heap de n elementos tiene altura h a dlog2@n CIAe: La consulta del máximo es sencilla y eficiente pues basta examinar la raíz.
  • 11. Cómo eliminar el máximo? 1 Ubicar al último elemento del montículo (el del último nivel más a la derecha) en la raíz, sustituyendo al máximo 2 Reestablecer el invariante (orden de heap) hundiendo la raíz. El método hundir intercambia un nodo dado con el mayor de sus dos hijos si el nodo es menor que alguno de ellos, y repete este paso hasta que el invariante de heap se ha reestablecido
  • 12.
  • 13. Cómo añadir un nuevo elemento? 1 Colocar el nuevo elemento como último elemento del montículo, justo a la derecha del último o como primero de un nuevo nivel 2 Reestablecer el orden de montıculo flotando el elemento recién añadido En el método flotar el nodo dado se compara con su nodo padre y se realiza el intercambio si éste es mayor que el padre, iterando este paso mientras sea necesario
  • 14. Puesto que la altura del heap es ¢@lognA el coste de inserciones y eliminaciones será y@lognA. Se puede implementar un heap mediante memoria dinámica, con apuntadores al hijo izquierdo y derecho y también al padre en cada nodo Pero es mucho más fácil y eficiente implementar los heaps mediante un vector. No se desperdicia demasiado espacio ya que el heap es quasi-completo; en caso necesario puede usarse el redimensionado
  • 15. Reglas para representar un heap en vector: 1 A‘I“ contiene la raíz. 2 Si Pi n entonces A‘Pi“ contiene al hijo izquierdo del elemento en A‘i“ y si Pi CI n entonces A‘Pi CI“ contiene al hijo derecho de A‘i“ 3 Si i ! P entonces A‘i=P“ contiene al padre de A‘i“
  • 16. Las reglas anteriores implican que los elementos del heap se ubican en posiciones consecutivas del vector, colocando la raíz en la primera posición y recorriendo el árbol por niveles, de izquierda a derecha. template <typename Elem, typename Prio> class ColaPrioridad { public: ... private: // la componente 0 no se usa; el constructor de la clase // inserta un elemento ficticio vector<pair<Elem, Prio> > h; int nelems; void flotar(int j) throw(); void hundir(int j) throw(); };
  • 17. template <typename Elem, typename Prio> bool ColaPrioridad<Elem,Prio>::vacia() const throw() { return nelems == 0; } template <typename Elem, typename Prio> Elem ColaPrioridad<Elem,Prio>::min() const throw(error) { if (nelems == 0) throw error(ColaVacia); return h[1].first; } template <typename Elem, typename Prio> Prio ColaPrioridad<Elem,Prio>::prio_min() const throw(error) { if (nelems == 0) throw error(ColaVacia); return h[1].second; }
  • 18. template <typename Elem, typename Prio> void ColaPrioridad<Elem,Prio>::inserta(cons Elem& x, cons Prio& p) throw(error) { ++nelems; h.push_back(make_pair(x, p)); flotar(nelems); } template <typename Elem, typename Prio> void ColaPrioridad<Elem,Prio>::elim_min() const throw(error) { if (nelems == 0) throw error(ColaVacia); swap(h[1], h[nelems]); --nelems; hundir(1); }
  • 19. // Versión recursiva. // Hunde el elemento en la posición j del heap // hasta reestablecer el orden del heap; por // hipótesis los subárboles del nodo j son heaps. // Coste: O(log(n/j)) template <typename Elem, typename Prio> void ColaPrioridad<Elem,Prio>::hundir(int j) throw() { // si j no tiene hijo izquierdo, hemos terminado if (2 * j > nelems) return; int minhijo = 2 * j; if (minhijo < nelems && h[minhijo].second > h[minhijo + 1].second) ++minhijo; // minhijo apunta al hijo de minima prioridad de j // si la prioridad de j es mayor que la de su menor hijo // intercambiar y seguir hundiendo if (h[j].second > h[minhijo].second) { swap(h[j], h[minhijo]); hundir(minhijo); } }
  • 20. // Versión iterativa. // Hunde el elemento en la posición j del heap // hasta reestablecer el orden del heap; por // hipótesis los subárboles del nodo j son heaps. // Coste: O(log(n/j)) template <typename Elem, typename Prio> void ColaPrioridad<Elem,Prio>::hundir(int j) throw() { bool fin = false; while (2 * j <= nelems && !fin) { int minhijo = 2 * j; if (minhijo < nelems && h[minhijo].second > h[minhijo + 1].second) ++minhijo; if (h[j].second > h[minhijo].second) { swap(h[j], h[minhijo]); j = minhijo; } else { fin = true; } } }
  • 21. // Flota al nodo j hasta reestablecer el orden del heap; // todos los nodos excepto el j satisfacen la propiedad // de heap // Coste: O(log j) template <typename Elem, typename Prio> void ColaPrioridad<Elem,Prio>::flotar(int j) throw() { // si j es la raíz, hemos terminado if (j == 1) return; int padre = j / 2; // si el padre tiene mayor prioridad // que j, intercambiar y seguir flotando if (h[j].second < h[padre].second) { swap(h[j], h[padre]); flotar(padre); } }
  • 22. Heapsort Heapsort (Williams, 1964) ordena un vector de n elementos construyendo un heap con los n elementos y extrayéndolos, uno a uno del heap a continuación. El propio vector que almacena a los n elementos se emplea para construir el heap, de modo que heapsort actúa in-situ y sólo requiere un espacio auxiliar de memoria constante. El coste de este algoritmo es ¢@n lognA (incluso en caso mejor) si todos los elementos son diferentes. En la práctica su coste es superior al de quicksort, ya que el factor constante multiplicativo del término n logn es mayor.
  • 23. // Ordena el vector v[1..n] // (v[0] no se usa) // de Elem’s de menor a mayor template <typename Elem> void heapsort(Elem v[], int n) { crea_max_heap(v, n); for (int i = n; i > 0; --i) { // saca el mayor elemento del heap swap(v[1], v[i]); // hunde el elemento de indice 1 // para reestablecer un max-heap en // el subvector v[1..i-1] hundir(v, i-1, 1); } }
  • 24.
  • 25.
  • 26.
  • 27. // Da estructura de max-heap al // vector v[1..n] de Elem’s; aquí // cada elemento se identifica con su // prioridad template <typename Elem> void crea_max_heap(Elem v[], int n) { for (int i = n/2; i > 0; --i) hundir(v, n, i); }
  • 28.
  • 29. Sea H@nA el coste en caso peor de heapsort y B@nA el coste de crear el heap inicial. El coste en caso peor de hundir@v; i  I; IA es y@logiA y por lo tanto H@nA a B@nAC i=nX i=1 y@logiA a B@nACy 0 @ X 1 i n log2 i 1 A a B@nACy@log@n3AA a B@nACy@n lognA Un análisis simple de B@nA indica que B@nA a y@n lognA ya que hay ¢@nA llamadas a hundir, cada una de las cuales tiene coste y@lognA Por tanto H@nA a y@n lognA, de hecho H@nA a ¢@n lognA en caso peor
  • 30. Podemos refinar el análisis de B@nA: B@nA a X 1 i ˜n=2™ y@log@n=iAA a y log n n=2 @n=PA3 ! a y log@PeAn=2 a y@nA Puesto que B@nA a @nA, podemos afirmar que B@nA a ¢@nA.
  • 31. Demostración alternativa: Sea h a dlog2@n CIAe la altura del heap. En el nivel h  I k hay como mucho Ph 1 k n CI Pk nodos y cada uno de ellos habrá de hundirse en caso peor hasta el nivel h  I; eso tiene coste y@kA
  • 32. Por lo tanto, B@nA a X 0 k h 1 y@kAn CI Pk a y 0 @n X 0 k h 1 k Pk 1 A a y 0 @n X k!0 k Pk 1 A a y@nA; ya que X k!0 k Pk a P: En general, si jrj I, X k!0 k ¡r k a r @I rA2 :
  • 33. Aunque H@nA a ¢@n lognA, el análisis detallado de B@nA es importante: utilizando un min-heap podemos hallar los k menores elementos en orden creciente de un vector (y en particular el k-ésimo) con coste: S@n; kA a B@nACk ¡y@lognA a y@n Ck lognA: y si k a y@n= lognA entonces S@n; kA a y@nA.