30
VI Colas de prioridad

VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Embed Size (px)

Citation preview

Page 1: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

VI Colas de prioridad

Page 2: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Una cola de prioridad (cat: cua de prioritat; ing:priority queue) es una coleccion de elementos dondecada elemento tiene asociado un valor susceptiblede ordenacion denominado prioridad. Una cola deprioridad se caracteriza por admitir inserciones denuevos elementos y la consulta y eliminacion delelemento de mınima prioridad. Analogamente sepueden definir colas de prioridad que admitan laconsulta y eliminacion del elemento de maximaprioridad en la coleccion.

Colas de prioridad 323

Page 3: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

En esta especificacion asumimos que el tipo Prio

ofrece una relacion de orden total <. Por otra parte,puede darse el caso de que existan varios elementoscon igual prioridad y en dicho caso es irrelevantecual de los elementos es devuelto por min oeliminado por elim min. En ocasiones se utilizauna operacion prio min que devuelve la mınimaprioridad.

Colas de prioridad 324

Page 4: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

template <typename Elem , typename Prio >

class ColaPrioridad

public:

// Constructora , crea una cola vacıa.

ColaPrioridad () throw(error);

// Destructora , constr. por copia y asignacion

~ColaPrioridad () throw ();

ColaPrioridad(const ColaPrioridad& P) throw(error);

ColaPrioridad& operator =( const ColaPrioridad P) throw(error);

// A~nade 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 esta 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 esta 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 esta vacıa.

void elim_min () throw(error );

// Devuelve cierto si y solo si la cola esta vacıa.

bool vacia() const throw ();

;

Colas de prioridad 325

Page 5: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Las colas de prioridad tienen multiples usos. Confrecuencia se emplean para implementar algoritmosvoraces. Este tipo de algoritmos suele tener unaiteracion principal, y una de las tareas a realizar encada una de dichas iteraciones es seleccionar unelemento de entre varios que minimiza (o maximiza)un cierto criterio de optimalidad local. El conjuntode elementos entre los que se ha de efectuar laseleccion es frecuentemente dinamico y admitirinserciones eficientes. Algunos de estos algoritmosincluyen:

Algoritmos de Kruskal y Prim para el calculo delarbol de expansion mınimo de un grafo etiquetado.

Algoritmo de Dijkstra para el calculo de caminosmınimos en un grafo etiquetado.

Construccion de codigos de Huffman (codigos bi-narios de longitud media mınima).

Otra tarea para la que obviamente podemos usaruna cola de prioridad es para ordenar.

Colas de prioridad 326

Page 6: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

// Tenemos dos arrays Peso y Simb con los pesos atomicos

// 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

// informacion de menor a mayor sımbolo en orden alfabetico

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 ();

Tambien se usan colas de prioridad para hallar elk-esimo elemento de un vector no ordenado. Secolocan los k primeros elementos del vector en unamax-cola de prioridad y a continuacion se recorre elresto del vector, actualizando la cola de prioridadcada vez que el elemento es menor que el mayor delos elementos de la cola, eliminando al maximo einsertando el elemento en curso.

Colas de prioridad 327

Page 7: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

La mayorıa de tecnicas empleadas en laimplementacion de diccionarios puede usarse paraimplementar colas de prioridad. La excepcion laconstituyen las tablas de dispersion y los tries. Sepuede usar una lista ordenada por prioridad. Tantola consulta como la eliminacion del mınimo sontriviales y su coste es Θ(1). Pero las insercionestienen coste lineal, tanto en caso peor como enpromedio.

Otra opcion es usar un arbol de busqueda(equilibrado o no), utilizando como criterio de ordende sus elementos las correspondientes prioridades.Hay que modificar ligeramente el invariante derepresentacion para admitir y tratar adecuadamentelas prioridades repetidas. Puede garantizarse en talcaso que todas las operaciones (inserciones,consultas, eliminaciones) tienen coste Θ(logn): encaso peor si el BST es equilibrado (AVL), y en casomedio si no lo es.

Colas de prioridad 328

Page 8: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Tambien pueden usarse skip lists con identicorendimiento al que ofrecen los BSTs (aunque loscostes son logarıtmicos solo en caso medio, dichocaso medio no depende ni del orden de insercion nide la existencia de pocas prioridades repetidas).

Si el conjunto de posibles prioridades es reducidoentonces sera conveniente emplear una tabla delistas, correspondiendo cada lista a una prioridad ointervalo reducido de prioridades.

En lo que resta estudiaremos una tecnica especıficapara la implementacion de colas de prioridad basadaen los denominados montıculos.

Colas de prioridad 329

Page 9: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Un montıculo (ing: heap) es un arbol binario tal que

1. todos las hojas (subarboles son vacıos) se situanen los dos ultimos niveles del arbol.

2. en el antepenultimo nivel existe a lo sumo unnodo interno con un solo hijo, que sera su hijoizquierdo, y todos los nodos a su derecha en elmismo nivel son nodos internos sin hijos.

3. el elemento (su prioridad) almacenado en un no-do cualquiera es mayor (menor) o igual que loselementos almacenados en sus hijos izquierdo yderecho.

Se dice que un montıculo es un arbol binarioquasi-completo debido a las propiedades 1-2. Lapropiedad 3 se denomina orden de montıculo, y sehabla de max-heaps o min-heaps segun que loselementos sean ≥ o ≤ ques sus hijos. En lo sucesivosolo consideraremos max-heaps.

Colas de prioridad 330

Page 10: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

76

72 34

59 63 17 29

37 33 29

nivel 0

nivel 1

nivel 2

nivel 3

nivel 4

altura = 4

hojas

n = 10

Colas de prioridad 331

Page 11: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

De las propiedades 1-3 se desprenden dosconsecuencias importantes:

1. El elemento maximo se encuentra en la raız.

2. Un heap de n elementos tiene altura

h = ⌈log2(n+1)⌉.

La consulta del maximo es sencilla y eficiente puesbasta examinar la raız.

Colas de prioridad 332

Page 12: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Como eliminar el maximo? Un procedimiento que seemplea a menudo consiste en ubicar al ultimoelemento del montıculo (el del ultimo nivel mas a laderecha) en la raız, sustituyendo al maximo; ellogarantiza que se preservan las propiedades 1-2. Perocomo la propiedad 3 deja eventualmente desatisfacerse, debe reestablecerse el invariante para locual se emplea un procedimiento privadodenominado hundir.

Este consiste en intercambiar un nodo con el mayorde sus dos hijos si el nodo es menor que alguno deellos, y repetir este paso hasta que el invariante sehaya reestablecido.

Colas de prioridad 333

Page 13: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

34

59 63 17 29

37 33 29

32

72

34

59 63 17 29

37 33 29

72

32

34

59 17 29

37 33 29

72

63

32

Colas de prioridad 334

Page 14: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Como anadir un nuevo elemento? Una posibilidadconsiste en colocar el nuevo elemento como ultimoelemento del montıculo, justo a la derecha delultimo o como primero de un nuevo nivel. Para ellohay que localizar al padre de la primera hoja ysustituirla por un nuevo nodo con el elemento ainsertar. A continuacion hay que reestablecer elorden de montıculo empleando para ello unprocedimiento flotar, que trabaja de manerasimilar pero a la inversa de hundir: el nodo encurso se compara con su nodo padre y se realiza elintercambio si este es mayor que el padre, iterandoeste paso mientras sea necesario.

Colas de prioridad 335

Page 15: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Puesto que la altura del heap es Θ(logn) el coste deinserciones y eliminaciones es O(logn). Se puedeimplementar un heap mediante memoria dinamica.La representacion elegida debe incluir apuntadoresal hijo izquierdo y derecho y tambien al padre, yresolver de manera eficaz la localizacion del ultimoelemento y del padre de la primera hoja.

Una alternativa atractiva es la implementacion deheaps mediante un vector. No se desperdiciademasiado espacio ya que el heap esquasi-completo. Las reglas para representar loselementos del heap en un vector son simples:

1. A[1] contiene la raız.

2. Si 2i≤ n entonces A[2i] contiene al hijo izquierdodel elemento en A[i] y si 2i + 1 ≤ n entoncesA[2i+1] contiene al hijo derecho de A[i].

3. Si idiv2≥ 1 entonces A[idiv2] contiene al padrede A[i].

Colas de prioridad 336

Page 16: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Notese que las reglas anteriores implican que loselementos del montıculo se ubican en posicionesconsecutivas del vector, colocando la raız en laprimera posicion y recorriendo el arbol por niveles,de izquierda a derecha.

template <typename Elem , typename Prio >

class ColaPrioridad

public:

...

private:

static const int MAX_ELEM = ...;

int nelems; // numero de elementos en el heap

// array de MAX_ELEMS pares <Elem , Prio >,

// la componente 0 no se usa

pair <Elem , Prio > h[MAX_ELEM + 1];

void flotar(int j) throw ();

void hundir(int j) throw ();

;

Colas de prioridad 337

Page 17: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

template <typename Elem , typename Prio >

bool ColaPrioridad <Elem ,Prio >:: vacia () const throw ()

return nelems == 0;

template <typename Elem , typename Prio >

void ColaPrioridad <Elem ,Prio >:: inserta(cons Elem& x,

cons Prio& p) throw(error)

if (nelems == MAX_ELEMS) throw error(ColaLlena );

++ nelems;

h[nelems] = make_pair(x, p);

flotar(nelems );

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 >:: elim_min () const throw(error)

if (nelems == 0) throw error(ColaVacia );

swap(h[1], h[nelems ]);

--nelems;

hundir (1);

Colas de prioridad 338

Page 18: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

// Version recursiva.

// Hunde el elemento en la posicion j del heap

// hasta reestablecer el orden del heap; por

// hipotesis los subarboles 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 );

Colas de prioridad 339

Page 19: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

// Version iterativa.

// Hunde el elemento en la posicion j del heap

// hasta reestablecer el orden del heap; por

// hipotesis los subarboles 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;

Colas de prioridad 340

Page 20: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

// 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 );

Colas de prioridad 341

Page 21: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Heapsort

Heapsort (Williams, 1964) ordena un vector de n

elementos construyendo un heap con los n

elementos y extrayendolos, uno a uno del heap acontinuacion. El propio vector que almacena a los n

elementos se emplea para construir el heap, demodo que heapsort actua in-situ y solo requiere unespacio auxiliar de memoria constante. El coste deeste algoritmo es Θ(n logn) (incluso en caso mejor)si todos los elementos son diferentes.

En la practica su coste es superior al de quicksort,ya que el factor constante multiplicativo del terminon logn es mayor.

Colas de prioridad 342

Page 22: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

// 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);

<_ <_1 k iA[1] = max A[k]

<_ <_ <_ <_A[1] A[i+1] A[i+2] ... A[n]

1

ordenado

n

heap

A

i

Colas de prioridad 343

Page 23: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

72 63 34 59 29 17 29 37 33 76

34

59 17 29

37 33

72

63

29

i = 9

76 72 34 59 63 17 29 37 33 29

i = 10

34

17 29

37 33 29

76

59 63

72

29 72 34 59 63 17 29 37 33 76

i = 9

34

59 63 17 29

37 33

72

29

Colas de prioridad 344

Page 24: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

33 59 34 37 29 17 29 63 72 76

34

17 29

59

2937

33

i = 7

59 37 34 33 29 17 29 63 72 76

i = 7

34

17 292933

37

59

33 63 34 59 29 17 29 37 72 76

34

17 29

37

59

33

63

29

i = 8

Colas de prioridad 345

Page 25: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

// 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);

Colas de prioridad 346

Page 26: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

13

2 5

27 8 15 10

4

13 2 5 27 8 15 10 4

i = 8

satisfacen la propiedad de heap

13

2

27 8 10

4

5

15

hundir(A, 8, 4)

hundir(A, 8, 3)

3

4

2

5 6 7

8

1

8 105

15

hundir(A, 8, 2)

hundir(A, 8, 1)

27

2

4

13

1

2 3

4 5 6 7

8

Colas de prioridad 347

Page 27: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Sea H(n) el coste en caso peor de heapsort y B(n)el coste de crear el heap inicial. El coste en casopeor de hundir(v, i−1,1) es O(log i) y por lo tanto

H(n) = B(n)+i=n

∑i=1

O(log i)

= B(n)+O

(

∑1≤i≤n

log2 i

)

= B(n)+O(log(n!)) = B(n)+O(n logn)

Un analisis “grueso” de B(n) indica queB(n) = O(n logn) ya que hay Θ(n) llamadas ahundir, cada una de las cuales tiene coste O(logn).Podemos concluir por tanto que H(n) = O(n logn).No es difıcil construir una entrada de tamano n talque H(n) = Ω(n logn) y por tanto H(n) = Θ(n logn)en caso peor. La demostracion de que el coste deheapsort en caso mejor3 es tambien Θ(n logn) esbastante mas complicada.

3Siendo todos los elementos distintos.

Colas de prioridad 348

Page 28: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Por otra parte, la cota dada para B(n) podemosrefinarla ya que

B(n) = ∑1≤i≤⌊n/2⌋

O(log(n/i))

= O

(

logn

n/2

(n/2)!

)

= O

(

log(2e)n/2)

= O(n).

Puesto que B(n) = Ω(n), podemos afirmar queB(n) = Θ(n).

Otra forma de demostrar que B(n) es lineal consisteen razonar del siguiente modo: Seah = ⌈log2(n+1)⌉ la altura del heap. En el nivelh−1− k hay como mucho

2h−1−k <n+1

2k

nodos y cada uno de ellos habra de hundirse en casopeor hasta el nivel h−1; eso tiene coste O(k).

Colas de prioridad 349

Page 29: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Por lo tanto,

B(n) = ∑0≤k≤h−1

O(k)n+1

2k

= O

(

n ∑0≤k≤h−1

k

2k

)

= O

(

n ∑k≥0

k

2k

)

= O(n),

ya que

∑k≥0

k

2k= 2.

En general, si r < 1,

∑k≥0

k · rk =r

(1− r)2.

Colas de prioridad 350

Page 30: VI Colas de prioridad - cs.upc.edups/downloads/matdoc/transparencias/ps/ps... · Tambi´en se usan colas de prioridad para hallar el k-´esimo elemento de un vector no ordenado. Se

Aunque globalmente H(n) = Θ(n logn), esinteresante el analisis detallado de B(n). Porejemplo, utilizando un min-heap podemos hallar losk menores elementos de un vector (y en particular elk-esimo) con coste:

S(n,k) = B(n)+ k ·O(logn)

= O(n+ k logn).

y si k = O(n/ logn) entonces S(n,k) = O(n).

Colas de prioridad 351