Una cola de prioridad es una estructura de datos que permite insertar elementos y eliminar el elemento mínimo de forma eficiente. Se implementa comúnmente mediante un montículo binario, el cual es un árbol binario completo donde cada nodo es menor que sus descendientes. Las operaciones de inserción y eliminación mínimo en un montículo binario pueden requerir intercambios recursivos de nodos para mantener esta propiedad.
Esta presentación le pertenece a Tania Landivar.
Las estructuras de datos lineales (vectores ) obliga afijar por adelantado el espacio a ocupar en memoria, de modo que, cuando se desea añadir un nuevo elemento que rebase el tamaño prefijado del array, no es posible realizar la operación sin que se produzca un error en tiempo de ejecución, para evitar esto se hace uso de las listas enlazadas.
Una lista enlazada es una colección o secuencia de elementos llamados nodos, dispuestos uno detrás de otro, en la que cada elemento se conecta al siguiente elemento por un “enlace” o “referencia”.
Tecnológico Nacional de México
Instituto Tecnológico Superior de Guasave
Ingeniería en Sistemas Computacionales
Estructura de Datos: AED-1026
Estructuras no lineales
Material de clase
I1M2010-T16: El tipo abstracto de las colas de prioridad en HaskellJosé A. Alonso
Se especifica el tipo abstracto de datos de las colas de prioridad, se presenta su implementación en Haskell mediante listas y se comprueban sus propiedades características con QuickCheck.
Este es el tema 16 del curso de introducción a Haskell. El código y los restantes temas se encuentran en http://www.cs.us.es/~jalonso/cursos/i1m-10/temas.html
Esta presentación le pertenece a Tania Landivar.
Las estructuras de datos lineales (vectores ) obliga afijar por adelantado el espacio a ocupar en memoria, de modo que, cuando se desea añadir un nuevo elemento que rebase el tamaño prefijado del array, no es posible realizar la operación sin que se produzca un error en tiempo de ejecución, para evitar esto se hace uso de las listas enlazadas.
Una lista enlazada es una colección o secuencia de elementos llamados nodos, dispuestos uno detrás de otro, en la que cada elemento se conecta al siguiente elemento por un “enlace” o “referencia”.
Tecnológico Nacional de México
Instituto Tecnológico Superior de Guasave
Ingeniería en Sistemas Computacionales
Estructura de Datos: AED-1026
Estructuras no lineales
Material de clase
I1M2010-T16: El tipo abstracto de las colas de prioridad en HaskellJosé A. Alonso
Se especifica el tipo abstracto de datos de las colas de prioridad, se presenta su implementación en Haskell mediante listas y se comprueban sus propiedades características con QuickCheck.
Este es el tema 16 del curso de introducción a Haskell. El código y los restantes temas se encuentran en http://www.cs.us.es/~jalonso/cursos/i1m-10/temas.html
El viernes por la mañana en Torrejón es terreno para la representación de uno de los pasajes del Viacrucis: el encuentro entre Jesús y la Verónica. Un pasaje que lleva cinco años representándose y que, en esta ocasión, tuvo que ser en el Templo. Así, el anunciado estreno de vestido de la imagen tendrá que esperar a otro año para pasear por las calles de la localidad.
China y Perú tienen antiguos vínculos económicos, políticos y culturales. Perú fue el primer país latinoamericano que estableció relaciones diplomáticas con China en 1874 (con el entonces Imperio Qing), y fue uno de los primeros de la región en establecer relaciones en noviembre de 1971 con la República Popular de China. Perú fue el primero en recibir en gran escala inmigrantes chinos a partir de 1849 y hasta el año 1872 se estima que 100 mil chinos llegaron al Perú. Esa es la razón por la cual Perú es el hogar de la comunidad china más grande de América Latina
1. 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.
2. 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.
3. 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
4. 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
5. 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.
6. 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