diff options
author | Joe Crayne <joe@jerkface.net> | 2018-07-05 20:19:28 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2018-07-05 20:20:19 -0400 |
commit | 93bfd69110df060a9c8ec6c194e0d30553d6e20d (patch) | |
tree | 62bd9a17e7e8ada810ba84fc96d070f8d19d5b3f | |
parent | 929789aff8840fb54026ffc46cfe46d4780ed0de (diff) |
O(1) size operation for MinMaxPSQ.
-rw-r--r-- | src/Data/MinMaxPSQ.hs | 69 |
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) |
11 | import Prelude hiding (null, take) | 11 | import Prelude hiding (null, take) |
12 | 12 | ||
13 | data MinMaxPSQ' k p v = MinMaxPSQ !(PSQ' k p v) !(PSQ' k (Down p) v) | 13 | data MinMaxPSQ' k p v = MinMaxPSQ !Int !(PSQ' k p v) !(PSQ' k (Down p) v) |
14 | type MinMaxPSQ k p = MinMaxPSQ' k p () | 14 | type MinMaxPSQ k p = MinMaxPSQ' k p () |
15 | 15 | ||
16 | empty :: MinMaxPSQ' k p v | 16 | empty :: MinMaxPSQ' k p v |
17 | empty = MinMaxPSQ PSQ.empty PSQ.empty | 17 | empty = MinMaxPSQ 0 PSQ.empty PSQ.empty |
18 | 18 | ||
19 | singleton' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v | 19 | singleton' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v |
20 | singleton' k v p = MinMaxPSQ (PSQ.singleton' k v p) (PSQ.singleton' k v (Down p)) | 20 | singleton' k v p = MinMaxPSQ 1 (PSQ.singleton' k v p) (PSQ.singleton' k v (Down p)) |
21 | 21 | ||
22 | null :: MinMaxPSQ' k p v -> Bool | 22 | null :: MinMaxPSQ' k p v -> Bool |
23 | null (MinMaxPSQ nq xq) = PSQ.null nq | 23 | null (MinMaxPSQ sz _ _) = sz==0 |
24 | {-# INLINE null #-} | ||
24 | 25 | ||
25 | size :: MinMaxPSQ' k p v -> Int | 26 | size :: MinMaxPSQ' k p v -> Int |
26 | size (MinMaxPSQ nq xq) = PSQ.size nq | 27 | size (MinMaxPSQ sz _ _) = sz |
28 | {-# INLINE size #-} | ||
27 | 29 | ||
28 | toList :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> [Binding' k p v] | 30 | toList :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> [Binding' k p v] |
29 | toList (MinMaxPSQ nq xq) = PSQ.toList nq | 31 | toList (MinMaxPSQ _ nq xq) = PSQ.toList nq |
30 | 32 | ||
31 | fromList :: (PSQKey k, Ord p) => [Binding' k p v] -> MinMaxPSQ' k p v | 33 | fromList :: (PSQKey k, Ord p) => [Binding' k p v] -> MinMaxPSQ' k p v |
32 | fromList kps = MinMaxPSQ (PSQ.fromList kps) | 34 | fromList 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 | ||
35 | findMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v) | 38 | findMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v) |
36 | findMin (MinMaxPSQ nq xq) = PSQ.findMin nq | 39 | findMin (MinMaxPSQ _ nq xq) = PSQ.findMin nq |
37 | 40 | ||
38 | findMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v) | 41 | findMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v) |
39 | findMax (MinMaxPSQ nq xq) = fmap (\(Binding k v (Down p)) -> Binding k v p) $ PSQ.findMin xq | 42 | findMax (MinMaxPSQ _ nq xq) = fmap (\(Binding k v (Down p)) -> Binding k v p) $ PSQ.findMin xq |
40 | 43 | ||
41 | insert :: (PSQKey k, Ord p) => k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p | 44 | insert :: (PSQKey k, Ord p) => k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p |
42 | insert k p (MinMaxPSQ nq xq) = MinMaxPSQ (PSQ.insert k p nq) | 45 | insert 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 | ||
45 | insert' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v | 49 | insert' :: (PSQKey k, Ord p) => k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v |
46 | insert' k v p (MinMaxPSQ nq xq) = MinMaxPSQ (PSQ.insert' k v p nq) | 50 | insert' 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 | ||
49 | delete :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v | 54 | delete :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v |
50 | delete k (MinMaxPSQ nq xq) = MinMaxPSQ (PSQ.delete k nq) (PSQ.delete k xq) | 55 | delete 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 | ||
52 | deleteMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v | 59 | deleteMin :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v |
53 | deleteMin (MinMaxPSQ nq xq) = case PSQ.minView nq of | 60 | deleteMin 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 | ||
57 | deleteMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v | 64 | deleteMax :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> MinMaxPSQ' k p v |
58 | deleteMax (MinMaxPSQ nq xq) = case PSQ.minView xq of | 65 | deleteMax 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 | ||
62 | minView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v) | 69 | minView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v) |
63 | minView (MinMaxPSQ nq xq) = fmap (\(Binding k v p, nq') -> (Binding k v p, MinMaxPSQ nq' (PSQ.delete k xq))) | 70 | minView (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 | ||
66 | maxView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v) | 73 | maxView :: (PSQKey k, Ord p) => MinMaxPSQ' k p v -> Maybe (Binding' k p v, MinMaxPSQ' k p v) |
67 | maxView (MinMaxPSQ nq xq) = fmap (\(Binding k v (Down p), xq') -> (Binding k v p, MinMaxPSQ (PSQ.delete k nq) xq')) | 74 | maxView (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. |
72 | insertTake :: (PSQKey k, Ord p) => Int -> k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p | 79 | insertTake :: (PSQKey k, Ord p) => Int -> k -> p -> MinMaxPSQ k p -> MinMaxPSQ k p |
73 | insertTake n k p q = take n $ insert k p q | 80 | insertTake 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. |
77 | insertTake' :: (PSQKey k, Ord p) => Int -> k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v | 87 | insertTake' :: (PSQKey k, Ord p) => Int -> k -> v -> p -> MinMaxPSQ' k p v -> MinMaxPSQ' k p v |
78 | insertTake' n k v p q = take n $ insert' k v p q | 88 | insertTake' 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 | ||
98 | lookup' :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> Maybe (p, v) | 111 | lookup' :: (PSQKey k, Ord p) => k -> MinMaxPSQ' k p v -> Maybe (p, v) |
99 | lookup' k (MinMaxPSQ q _) = PSQ.lookup k q | 112 | lookup' k (MinMaxPSQ _ q _) = PSQ.lookup k q |