Tema 16: El tipo abstracto de datos de las colas de prioridad
Índice
1. Especificación del TAD de las colas de prioridad
1.1. Signatura del TAD colas de prioridad
1.1.1. Descripción de las colas de prioridad
- Una cola de prioridad es una cola en la que cada elemento tiene asociada una prioridad. La operación de extracción siempre elige el elemento de menor prioridad.
- Ejemplos:
- La cola de las ciudades ordenadas por su distancia al destino final.
- Las colas de las tareas pendientes ordenadas por su fecha de terminación.
1.1.2. Signatura de las colas de prioridad
Signatura:
vacia :: Ord a => CPrioridad a inserta :: Ord a => a -> CPrioridad a -> CPrioridad a primero :: Ord a => CPrioridad a -> a resto :: Ord a => CPrioridad a -> CPrioridad a esVacia :: Ord a => CPrioridad a -> Bool valida :: Ord a => CPrioridad a -> Bool
- Descripción de las operaciones:
vacia
es la cola de prioridad vacía.(inserta x c)
añade el elementox
a la cola de prioridadc
.(primero c)
es el primer elemento de la cola de prioridadc
.(resto c)
es el resto de la cola de prioridadc
.(esVacia c)
se verifica si la cola de prioridadc
es vacía.(valida c)
se verifica sic
es una cola de prioridad válida.
1.2. Propiedades del TAD de las colas de prioridad
inserta x (inserta y c) == inserta y (inserta x c)
primero (inserta x vacia) == x
- Si
x <= y
, entoncesprimero (inserta y (inserta x c)) == primero (inserta x c)
resto (inserta x vacia) == vacia
- Si
x <= y
, entoncesresto (inserta y (inserta x c)) == inserta y (resto (inserta x c))
esVacia vacia
not (esVacia (inserta x c))
2. Implementaciones del TAD de las colas de prioridad
2.1. Las colas de prioridad como listas
Cabecera del módulo:
module Tema_16.ColaDePrioridadConListas (CPrioridad, vacia, -- Ord a => CPrioridad a inserta, -- Ord a => a -> CPrioridad a -> CPrioridad a primero, -- Ord a => CPrioridad a -> a resto, -- Ord a => CPrioridad a -> CPrioridad a esVacia, -- Ord a => CPrioridad a -> Bool valida -- Ord a => CPrioridad a -> Bool ) where
Colas de prioridad mediante listas:
newtype CPrioridad a = CP [a] deriving (Eq, Show)
Ejemplo: La cola de prioridad obtenida añadiéndole a la cola vacía los elementos 3, 1, 7, 2 y 9 es
λ> foldr inserta vacia [3,1,7,2,9] CP [1,2,3,7,9]
(valida c)
se verifica sic
es una cola de prioridad válida; es decir, está ordenada crecientemente. Por ejemplo,valida (CP [1,3,5]) == True valida (CP [1,5,3]) == False
Su definición es
valida :: Ord a => CPrioridad a -> Bool valida (CP xs) = ordenada xs where ordenada (x:y:zs) = x <= y && ordenada (y:zs) ordenada _ = True
vacia
es la cola de prioridad vacía. Por ejemplo,λ> vacia CP []
Su definición es
vacia :: Ord a => CPrioridad a vacia = CP []
(inserta x c)
es la cola obtenida añadiendo el elementox
a la cola de prioridadc
. Por ejemplo,λ> inserta 5 (foldr inserta vacia [3,1,7,2,9]) CP [1,2,3,5,7,9]
Su definición es
inserta :: Ord a => a -> CPrioridad a -> CPrioridad a inserta x (CP q) = CP (ins x q) where ins x [] = [x] ins x r@(e:r') | x < e = x:r | otherwise = e:ins x r'
(primero c)
es el primer elemento de la cola de prioridadc
.primero (foldr inserta vacia [3,1,7,2,9]) == 1
Su definición es
primero :: Ord a => CPrioridad a -> a primero (CP(x:_)) = x primero _ = error "primero: cola vacia"
(resto c)
es la cola de prioridad obtenida eliminando el primer elemento de la cola de prioridadc
. Por ejemplo,resto (foldr inserta vacia [3,1,7,2,9]) == CP [2,3,7,9]
Su definición es
resto :: Ord a => CPrioridad a -> CPrioridad a resto (CP (_:xs)) = CP xs resto _ = error "resto: cola vacia"
(esVacia c)
se verifica si la cola de prioridadc
es vacía. Por ejemplo,esVacia (foldr inserta vacia [3,1,7,2,9]) == False esVacia vacia == True
Su definición es
esVacia :: Ord a => CPrioridad a -> Bool esVacia (CP xs) = null xs
2.2. Las colas de prioridad como montículos
La implementación de las colas de prioridad como montículos
(ColaDePrioridadConMonticulos.hs
) se encuentra en el
tema 20 (El TAD de los montículos).
3. Comprobación de las implementaciones con QuickCheck
3.1. Pragma y librerías auxiliares
Al principio del fichero se añade
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE FlexibleInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
Importación de la implementación de colas de prioridad que se desea verificar.
import Tema-16.ColaDePrioridadConListas -- import Tema_20.ColaDePrioridadConMonticulos -- import I1M.ColaDePrioridad
Importación de las librerías de comprobación
import Test.QuickCheck
3.2. Generador de colas de prioridad
genCPrioridad
es un generador de colas de prioridad. Por ejemplo,λ> sample genCPrioridad CP [-4] CP [-2,-1,-1,2,5] ...
genCPrioridad :: (Arbitrary a, Num a, Ord a) => Gen (CPrioridad a) genCPrioridad = do xs <- listOf arbitrary return (foldr inserta vacia xs) instance (Arbitrary a, Num a, Ord a) => Arbitrary (CPrioridad a) where arbitrary = genCPrioridad
Las colas de prioridad producidas por
genCPrioridad
son válidas.prop_genCPrioridad_correcto :: CPrioridad Int -> Bool prop_genCPrioridad_correcto c = valida c
Comprobación.
λ> quickCheck prop_genCPrioridad_correcto +++ OK, passed 100 tests.
3.3. Especificación de las propiedades de las colas de prioridad
Si se añade dos elementos a una cola de prioridad se obtiene la misma cola de prioridad idependientemente del orden en que se añadan los elementos.
prop_inserta_conmuta :: Int -> Int -> CPrioridad Int -> Bool prop_inserta_conmuta x y c = inserta x (inserta y c) == inserta y (inserta x c)
La cabeza de la cola de prioridad obtenida anadiendo un elemento
x
a la cola de prioridad vacía esx
.prop_primero_inserta_vacia :: Int -> CPrioridad Int -> Bool prop_primero_inserta_vacia x c = primero (inserta x vacia) == x
El primer elemento de una cola de prioridad
c
no cambia cuando se le añade un elemento mayor o igual que algún elemento dec
.prop_primero_inserta :: Int -> Int -> CPrioridad Int -> Property prop_primero_inserta x y c = x <= y ==> primero (inserta y c') == primero c' where c' = inserta x c
El resto de añadir un elemento a la cola de prioridad vacía es la cola vacía.
prop_resto_inserta_vacia :: Int -> Bool prop_resto_inserta_vacia x = resto (inserta x vacia) == vacia
El resto de la cola de prioridad obtenida añadiendo un elemento
y
a una colac'
(que tiene algún elemento menor o igual quey
) es la cola que se obtiene añadiendoy
al resto dec'
.prop_resto_inserta :: Int -> Int -> CPrioridad Int -> Property prop_resto_inserta x y c = x <= y ==> resto (inserta y c') == inserta y (resto c') where c' = inserta x c
vacia
es una cola vacía.prop_vacia_es_vacia :: Bool prop_vacia_es_vacia = esVacia (vacia :: CPrioridad Int)
Si se añade un elemento a una cola de prioridad se obtiene una cola no vacía.
prop_inserta_no_es_vacia :: Int -> CPrioridad Int -> Bool prop_inserta_no_es_vacia x c = not (esVacia (inserta x c))
3.4. Comprobación de las propiedades
Para verificar todas las propiedades se escribe
return [] verifica = $quickCheckAll
Comprobación de las propiedades de las colas de prioridad
λ> verifica === prop_genCPrioridad_correcto from ColaDePrioridadPropiedades.hs:45 === +++ OK, passed 100 tests. === prop_inserta_conmuta from ColaDePrioridadPropiedades.hs:59 === +++ OK, passed 100 tests. === prop_primero_inserta_vacia from ColaDePrioridadPropiedades.hs:69 === +++ OK, passed 100 tests. === prop_primero_inserta from ColaDePrioridadPropiedades.hs:79 === +++ OK, passed 100 tests. === prop_resto_inserta_vacia from ColaDePrioridadPropiedades.hs:90 === +++ OK, passed 100 tests. === prop_resto_inserta from ColaDePrioridadPropiedades.hs:101 === +++ OK, passed 100 tests. === prop_vacia_es_vacia from ColaDePrioridadPropiedades.hs:111 === +++ OK, passed 1 tests. === prop_inserta_no_es_vacia from ColaDePrioridadPropiedades.hs:120 === +++ OK, passed 100 tests. True
4. Material complementario
El código del tema se encuentra en este los siguientes enlaces
- Implementación de las colas de prioridad como listas.
- Propiedades del TAD de las colas de prioridad.
Este tema también se encuentra en los siguientes formatos:
- Como transparencias en PDF.
- Como libro interactivo en IHaskell sobre Jupyter.
- Como vídeo de clase.
5. Referencias
- F. Rabhi y G. Lapalme. Algorithms: A functional programming approach.
- Cap. 5.4. Priority queues.