summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2018-07-05 20:19:28 -0400
committerJoe Crayne <joe@jerkface.net>2018-07-05 20:20:19 -0400
commit93bfd69110df060a9c8ec6c194e0d30553d6e20d (patch)
tree62bd9a17e7e8ada810ba84fc96d070f8d19d5b3f
parent929789aff8840fb54026ffc46cfe46d4780ed0de (diff)
O(1) size operation for MinMaxPSQ.
-rw-r--r--src/Data/MinMaxPSQ.hs69
1 files changed, 41 insertions, 28 deletions
diff --git a/src/Data/MinMaxPSQ.hs b/src/Data/MinMaxPSQ.hs
index 3b9a4d6c..e7d7c760 100644
--- a/src/Data/MinMaxPSQ.hs
+++ b/src/Data/MinMaxPSQ.hs
@@ -10,72 +10,85 @@ import qualified Data.Wrapper.PSQ as PSQ
10 ;import Data.Wrapper.PSQ as PSQ hiding (insert, insert', null, size) 10 ;import Data.Wrapper.PSQ as PSQ hiding (insert, insert', null, size)
11import Prelude hiding (null, take) 11import Prelude hiding (null, take)
12 12
13data MinMaxPSQ' k p v = MinMaxPSQ !(PSQ' k p v) !(PSQ' k (Down p) v) 13data MinMaxPSQ' k p v = MinMaxPSQ !Int !(PSQ' k p v) !(PSQ' k (Down p) v)
14type MinMaxPSQ k p = MinMaxPSQ' k p () 14type MinMaxPSQ k p = MinMaxPSQ' k p ()
15 15
16empty :: MinMaxPSQ' k p v 16empty :: MinMaxPSQ' k p v
17empty = MinMaxPSQ PSQ.empty PSQ.empty 17empty = MinMaxPSQ 0 PSQ.empty PSQ.empty
18 18
19singleton' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v 19singleton' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v
20singleton' k v p = MinMaxPSQ (PSQ.singleton' k v p) (PSQ.singleton' k v (Down p)) 20singleton' k v p = MinMaxPSQ 1 (PSQ.singleton' k v p) (PSQ.singleton' k v (Down p))
21 21
22null :: MinMaxPSQ' k p v -> Bool 22null :: MinMaxPSQ' k p v -> Bool
23null (MinMaxPSQ nq xq) = PSQ.null nq 23null (MinMaxPSQ sz _ _) = sz==0
24{-# INLINE null #-}
24 25
25size :: MinMaxPSQ' k p v -> Int 26size :: MinMaxPSQ' k p v -> Int
26size (MinMaxPSQ nq xq) = PSQ.size nq 27size (MinMaxPSQ sz _ _) = sz
28{-# INLINE size #-}
27 29
28toList :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> [Binding' k p v] 30toList :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> [Binding' k p v]
29toList (MinMaxPSQ nq xq) = PSQ.toList nq 31toList (MinMaxPSQ _ nq xq) = PSQ.toList nq
30 32
31fromList :: (PSQKey k, Ord p) => [Binding' k p v] -> MinMaxPSQ' k p v 33fromList :: (PSQKey k, Ord p) => [Binding' k p v] -> MinMaxPSQ' k p v
32fromList kps = MinMaxPSQ (PSQ.fromList kps) 34fromList kps = let nq = PSQ.fromList kps
33 (PSQ.fromList $ map (\(Binding k v p) -> Binding k v (Down p)) kps) 35 xq = PSQ.fromList $ map (\(Binding k v p) -> Binding k v (Down p)) kps
36 in MinMaxPSQ (PSQ.size nq) nq xq
34 37
35findMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v) 38findMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v)
36findMin (MinMaxPSQ nq xq) = PSQ.findMin nq 39findMin (MinMaxPSQ _ nq xq) = PSQ.findMin nq
37 40
38findMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v) 41findMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v)
39findMax (MinMaxPSQ nq xq) = fmap (\(Binding k v (Down p)) -> Binding k v p) $ PSQ.findMin xq 42findMax (MinMaxPSQ _ nq xq) = fmap (\(Binding k v (Down p)) -> Binding k v p) $ PSQ.findMin xq
40 43
41insert :: (PSQKey k, Ord p) => k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p 44insert :: (PSQKey k, Ord p) => k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p
42insert k p (MinMaxPSQ nq xq) = MinMaxPSQ (PSQ.insert k p nq) 45insert k p (MinMaxPSQ sz nq xq) = case PSQ.insertView k p () nq of
43 (PSQ.insert k (Down p) xq) 46 (Just _ ,nq') -> MinMaxPSQ sz nq' (PSQ.insert k (Down p) xq)
47 (Nothing,nq') -> MinMaxPSQ (sz+1) nq' (PSQ.insert k (Down p) xq)
44 48
45insert' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v 49insert' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v
46insert' k v p (MinMaxPSQ nq xq) = MinMaxPSQ (PSQ.insert' k v p nq) 50insert' k v p (MinMaxPSQ sz nq xq) = case PSQ.insertView k p v nq of
47 (PSQ.insert' k v (Down p) xq) 51 (Just _ ,nq') -> MinMaxPSQ sz nq' (PSQ.insert' k v (Down p) xq)
52 (Nothing,nq') -> MinMaxPSQ (sz+1) nq' (PSQ.insert' k v (Down p) xq)
48 53
49delete :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v 54delete :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v
50delete k (MinMaxPSQ nq xq) = MinMaxPSQ (PSQ.delete k nq) (PSQ.delete k xq) 55delete k q@(MinMaxPSQ sz nq xq) = case PSQ.deleteView k nq of
56 Just (_,_,nq') -> MinMaxPSQ (sz - 1) nq' (PSQ.delete k xq)
57 Nothing -> q
51 58
52deleteMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v 59deleteMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v
53deleteMin (MinMaxPSQ nq xq) = case PSQ.minView nq of 60deleteMin q@(MinMaxPSQ sz nq xq) = case PSQ.minView nq of
54 Just (Binding k _ _, nq') -> MinMaxPSQ nq' (PSQ.delete k xq) 61 Just (Binding k _ _, nq') -> MinMaxPSQ (sz - 1) nq' (PSQ.delete k xq)
55 Nothing -> MinMaxPSQ nq xq 62 Nothing -> q
56 63
57deleteMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v 64deleteMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v
58deleteMax (MinMaxPSQ nq xq) = case PSQ.minView xq of 65deleteMax q@(MinMaxPSQ sz nq xq) = case PSQ.minView xq of
59 Just (Binding k _ _, xq') -> MinMaxPSQ (PSQ.delete k nq) xq' 66 Just (Binding k _ _, xq') -> MinMaxPSQ (sz - 1) (PSQ.delete k nq) xq'
60 Nothing -> MinMaxPSQ nq xq 67 Nothing -> q
61 68
62minView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v) 69minView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v)
63minView (MinMaxPSQ nq xq) = fmap (\(Binding k v p, nq') -> (Binding k v p, MinMaxPSQ nq' (PSQ.delete k xq))) 70minView (MinMaxPSQ sz nq xq) = fmap (\(Binding k v p, nq') -> (Binding k v p, MinMaxPSQ (sz-1) nq' (PSQ.delete k xq)))
64 $ PSQ.minView nq 71 $ PSQ.minView nq
65 72
66maxView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v) 73maxView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v)
67maxView (MinMaxPSQ nq xq) = fmap (\(Binding k v (Down p), xq') -> (Binding k v p, MinMaxPSQ (PSQ.delete k nq) xq')) 74maxView (MinMaxPSQ sz nq xq) = fmap (\(Binding k v (Down p), xq') -> (Binding k v p, MinMaxPSQ (sz-1) (PSQ.delete k nq) xq'))
68 $ PSQ.minView xq 75 $ PSQ.minView xq
69 76
70-- | Maintains a bounded 'MinMaxPSQ' by deleting the maximum element if the 77-- | Maintains a bounded 'MinMaxPSQ' by deleting the maximum element if the
71-- insertion would cause the queue to have too many elements. 78-- insertion would cause the queue to have too many elements.
72insertTake :: (PSQKey k, Ord p) => Int -> k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p 79insertTake :: (PSQKey k, Ord p) => Int -> k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p
73insertTake n k p q = take n $ insert k p q 80insertTake n k p q
81 | size q < n = insert k p q
82 | size q == n = insert k p $ deleteMax q
83 | otherwise = take n $ insert k p q
74 84
75-- | Maintains a bounded 'MinMaxPSQ\'' by deleting the maximum element if the 85-- | Maintains a bounded 'MinMaxPSQ\'' by deleting the maximum element if the
76-- insertion would cause the queue to have too many elements. 86-- insertion would cause the queue to have too many elements.
77insertTake' :: (PSQKey k, Ord p) => Int -> k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v 87insertTake' :: (PSQKey k, Ord p) => Int -> k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v
78insertTake' n k v p q = take n $ insert' k v p q 88insertTake' n k v p q
89 | size q < n = insert' k v p q
90 | size q == n = insert' k v p $ deleteMax q
91 | otherwise = take n $ insert' k v p q
79 92
80 93
81-- | Truncate the 'MinMaxPSQ' to the given number of lowest priority elements. 94-- | Truncate the 'MinMaxPSQ' to the given number of lowest priority elements.
@@ -96,4 +109,4 @@ takeView !n !q | (size q <= n) = ([], q)
96 109
97 110
98lookup' :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> Maybe (p, v) 111lookup' :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> Maybe (p, v)
99lookup' k (MinMaxPSQ q _) = PSQ.lookup k q 112lookup' k (MinMaxPSQ _ q _) = PSQ.lookup k q