Qué son las colas de prioridad

6

Click here to load reader

Transcript of Qué son las colas de prioridad

Page 1: Qué son las colas de prioridad

Qué son las colas de prioridad

Una cola de prioridad es una estructura de datos que permite al menos las siguientes dos

operaciones: insertar, que añade elementos a la cola, y eliminar mínimo, que busca, devuelve y elimina el elemento mínimo de la cola.

La implantación de la cola de prioridad en la biblioteca de clases de DSTool se realiza mediante un montículo binario.

Para que una estructura sea un montículo binario debe cumplir dos propiedades:

Un montículo es un árbol binario completamente lleno, con la posible excepción del nivel más

bajo, el cual se rellena de izquierda a derecha. Estos árboles se denominan árboles binarios completos.

Todo nodo debe ser menor que todos sus descendientes. Por lo tanto, el mínimo estará en la raíz y su búsqueda y eliminación se podrá realizar rápidamente.

Los árboles binarios completos son muy regulares, lo que permite que los montículos puedan ser representados mediante simples arrays sin necesidad de punteros. En una representación con arrays los hijos de un elemento colocado en la posición i estarían en las posiciones 2i y 2i+1 ( hijo izquierdo e hijo derecho respectivamente), y el padre en la posición E( i/2 ) (parte entera de i/2 ).

En el siguiente ejemplo:

En el árbol se puede apreciar claramente los hijos de B ( D y E) y su padre ( A). A través de la representación con un array se podría obtener la misma información:

Nodo B en la posición 2.

Hijo izquierdo: posición 2*2 = 4. Luego el hijo izquierdo es D.

Hijo derecho: posición 2*2+1 = 5. Luego el hijo derecho es E.

Padre: posición E( 2/2) = 0. Luego el padre es A.

Operaciones básicas de las colas de prioridad

Las dos operaciones básicas de las colas de prioridad son insertar y eliminar mínimo. Vamos a conocer su funcionamiento.

Page 2: Qué son las colas de prioridad

Insertar

La inserción en una cola de prioridad puede ser algo muy simple o una operación compleja.

Inicialmente se inserta el nuevo elemento en la primera posición libre de la cola de prioridad, en el montículo representado arriba se insertaría como el hijo derecho del nodo C. En el caso de que el nuevo elemento fuese mayor que su padre la operación de inserción habría finalizado, ya que seguiría manteniendo la condición de orden de los montículos. Por supuesto este era el caso simple...

La complejidad se produce cuando el nodo insertado es menor que su padre. Si repasamos las condiciones para que una estructura sea un montículo binario observaremos que es necesario que cada nodo sea menor que sus hijos, por lo que si dejásemos la estructura así, con el nuevo nodo en la última posición, esa estructura ya no sería un montículo.

Para solucionar este problema lo que se realiza es un intercambio entre padre e hijo. Con este intercambio ya estaría solucionado el problema, pero ¿qué sucede si el nuevo nodo (que se ha intercambiado con el padre) es aún más pequeño que su nuevo padre?. Pues la respuesta es simple, se volvería a realizar un nuevo intercambio del nuevo nodo con su nuevo padre, prolongándose estos intercambios hasta que el nuevo nodo sea mayor que sus padre o hasta que el nuevo nodo llegue a la raíz.

Vamos a ver este caso con un ejemplo gráfico:

Sobre el montículo inicial, representado por los nodos negros, insertamos un nuevo elemento con valor 3, representado por el nodo rojo.

Como vemos, si se dejase en esa posición el nuevo nodo, se violaría la condición de orden del montículo, ya que el nodo 8 no es menor que todos sus descendientes ( 3 es menor que 8). Por lo tanto se realiza un intercambio entre 8 y 3.

Page 3: Qué son las colas de prioridad

La situación ahora entre el nodo 8 y el nodo 3 es correcto. Perfecto. Pero si observamos un poco más arriba, veremos que el nodo padre del nuevo nodo, el 4, viola de nuevo la condicón de orden del montículo. Por lo tanto volvemos a intercambiar posiciones entre 3 y 4.

Ahora sí que ya podemos decir que el montículo es correcto, ya que el nuevo nodo 3 sí que es mayor que la raíz 1.

Véase que la condición de orden sólo obliga a que un nodo sea menor que sus descendientes, no a que sea menor que los nodos que estén en un nivel inferior. Esto se puede apreciar con el hijo izquierdo de 2 ( valor 5) y el nodo con valor 4 situado en el mismo nivel. Nodo 4 es menor que nodo 5 y está en un nivel inferior. Esto no importa, el montículo es correcto.

Eliminar mínimo

La operación eliminar mínimo consta de dos partes, la búsqueda del mínimo y su eliminación. La búsqueda es fácil, el mínimo es siempre la raíz. Eliminarlo es lo complejo.

Al eliminar el mínimo se crea un hueco en la raíz, este hueco se cubrirá con el menor de uno de los siguientes nodos, sus hijos o el último nodo del montículo. Al realizar este trasvase, se creará un nuevo hueco en el lugar del nodo que promocionó a la raíz, excepto si el nodo que promocionó fue el último del montículo. Para cubrir este nuevo hueco se vuelve a realizar la misma acción, se cubre con

Page 4: Qué son las colas de prioridad

el menor de sus hijos o con el último nodo si éste es más pequeño. Este procedimiento se repetirá

recursivamente hasta que el hueco sea cubierto por el último nodo del montículo original, caso que se producirá cuando dicho nodo sea menor que los nodos hijo del hueco o cuando el hueco esté situado en un nodo hoja.

Este proceso se apreciará mejor gráficamente:

Al eliminar el mínimo (1), se crea un hueco en la raíz que será cubierto por el menor de los siguientes nodos: hijo izquierdo (2), hijo derecho (3), último nodo (4). En este caso el nodo que promociona será el 2.

Para ocupar el nuevo nodo se tienen en cuenta los siguientes nodos: hijo izquierdo (5), hijo derecho (8), último nodo (4). El mínimo es el 4, por lo tanto es el que ocupa el hueco y se acaba la operación de inserción. La estructura obtenida es un montículo correcto.

Otras operaciones

En una cola de prioridad el resto de operaciones son secundarias y cada cola puede implementar unos métodos distintos. Por esta razón no entraré en otras operaciones.

Únicamente comentar que las colas de prioridad pueden ser también de máximos, caso inverso totalmente al visto en esta página. Es importante también advertir que en un montículo de mínimos la

operación eliminar máximo no es ni mucho menos tan eficiente como la operación eliminar mínimo, ya

Page 5: Qué son las colas de prioridad

que habría que realizar un recorrido completo del árbol para encontrar el máximo. De la misma forma sucede con la operación eliminar mínimo en un montículo de máximos.

Insertar

El proceso de inserción en una tabla hash es muy simple y sencillo. Sobre el elemento que se desea

insertar se aplica la función de dispersión. El valor obtenido tras la aplicación de esta función será el índice de la tabla en el que se insertará el nuevo elemento.

Veamos este proceso con un ejemplo. Sobre la siguiente tabla hash se desea introducir un nuevo elemento, la cadena azul. Sobre este valor se aplica la función de dispersión, obteniendo el índice 2.

El resultado de la inserción sería el siguiente:

En el caso de que se produzca una colisión al tratar de insertar el nuevo elemento, el procedimiento será distinto en función del tipo de hash con el que se esté tratando.

Encadenamiento separado: El nuevo elemento se añadirá al final de la lista que se inicia en la

posición indicada por el valor que retornó la función de dispersión.

Direccionamiento abierto: En este caso, se busca una nueva posición en la que almacenar el nuevo valor.

Page 6: Qué son las colas de prioridad

Borrar

El borrado en una tabla hash es muy sencillo y se realiza de forma muy eficiente. Una vez indicada la clave del objeto a borrar, se procederá a eliminar el valor asociado a dicha clave de la tabla.

Esta operación se realiza en tiempo constante, sin importar el tamaño de la tabla o el número de elementos que almacene en ese momento la estructura de datos. Esto es así ya que al ser la tabla una

estructura a la que se puede acceder directamente a través de las claves, no es necesario recorrer toda la estructura para localizar un elemento determinado.

Si sobre la tabla resultante de la inserción del elemento azul realizamos el borrado del elemento negro, la tabla resultante sería la siguiente:

Otras operaciones

Una de las principales operaciones que se pueden realizar en las tablas hash es la redispersión. La

redispersión se suele realizar cuando el factor de carga(número de elementos / capacidad de la tabla) de la tabla supera cierto umbral.

La redispersión consiste en pasar todos los elementos de la tabla original a una nueva tabla de un tamaño mayor. De esta forma, se reduce el factor de carga de la tabla