module Data.DEPQ (
DEPQ,
empty, fromList,
null,
insert, deleteMin, deleteMax, popMin, popMax,
findMin, findMax,
topK, bottomK
) where
import Data.Maybe (fromMaybe)
import Data.Ord (Down(..))
import qualified Data.Sequence as S (Seq, empty, (|>))
import Control.DeepSeq (NFData (rnf))
import qualified Data.IntPSQ as P (IntPSQ, empty, null, insert, delete, member, toList, fromList, findMin, delete, deleteMin)
import Prelude hiding (null)
data DEPQ p a = DEPQ {
minHeap :: P.IntPSQ p a
, maxHeap :: P.IntPSQ (Down p) a
} deriving (Eq, Show)
instance (NFData p, NFData a) => NFData (DEPQ p a) where
rnf (DEPQ mi ma) = rnf mi `seq` rnf ma
insert :: (Ord p) =>
Int
-> p
-> a
-> DEPQ p a -> DEPQ p a
insert k p v (DEPQ mi ma) = DEPQ mi' ma'
where
mi' = P.insert k p v mi
ma' = P.insert k (Down p) v ma
{-# INLINE insert #-}
empty :: DEPQ p a
empty = DEPQ P.empty P.empty
fromList :: (Foldable t, Ord p) =>
t (Int, p, a)
-> DEPQ p a
fromList = foldl insf empty where
insf acc (k,p,v) = insert k p v acc
{-# inline fromList #-}
null :: DEPQ p v -> Bool
null (DEPQ mi ma) = P.null mi && P.null ma
deleteMin :: Ord p => DEPQ p a -> DEPQ p a
deleteMin de@(DEPQ mi ma) = case P.findMin mi of
Nothing -> de
Just (imin, _, _) -> DEPQ mi' ma' where
mi' = P.deleteMin mi
ma' = P.delete imin ma
{-# INLINE deleteMin #-}
deleteMax :: Ord p => DEPQ p a -> DEPQ p a
deleteMax de@(DEPQ mi ma) = case P.findMin ma of
Nothing -> de
Just (imax, _, _) -> DEPQ mi' ma' where
ma' = P.deleteMin ma
mi' = P.delete imax mi
{-# INLINE deleteMax #-}
findMin :: Ord p => DEPQ p v -> Maybe (Int, p, v)
findMin (DEPQ mi _) = P.findMin mi
{-# inline findMin #-}
findMax :: Ord p => DEPQ p v -> Maybe (Int, p, v)
findMax (DEPQ _ ma) = f <$> P.findMin ma
where
f (i, Down p, v) = (i, p, v)
{-# inline findMax #-}
popMin :: Ord p => DEPQ p v -> Maybe ((Int, p, v), DEPQ p v)
popMin q = do
x <- findMin q
let q' = deleteMin q
pure (x, q')
popMax :: Ord p => DEPQ p v -> Maybe ((Int, p, v), DEPQ p v)
popMax q = do
x <- findMax q
let q' = deleteMax q
pure (x, q')
topK :: Ord p => Int -> DEPQ p v -> S.Seq (Int, p, v)
topK = popK popMax
bottomK :: Ord p => Int -> DEPQ p v -> S.Seq (Int, p, v)
bottomK = popK popMin
popK :: (q -> Maybe (a, q))
-> Int
-> q
-> S.Seq a
popK pop kk qq = fromMaybe S.empty $ go qq kk S.empty where
go _ 0 acc = pure acc
go q k acc = do
(x, q') <- pop q
go q' (k - 1) (acc S.|> x)