-
Notifications
You must be signed in to change notification settings - Fork 0
/
Queue.hs
105 lines (89 loc) · 3.6 KB
/
Queue.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
module Queue where
import qualified Data.List as List
import GHC.Exts(IsList(..))
--import Control.Exception(assert)
------------------------------------------------------------------
data StrictList a
= StrictNil
| StrictCons !a !(StrictList a)
instance Functor StrictList where
fmap f = go where
go StrictNil = StrictNil
go (StrictCons x xs) = StrictCons (f x) (go xs)
------------------------------------------------------------------
class Queue f where
emptyQueue :: f a
dequeue :: f a -> Maybe (a, f a)
enqueue :: f a -> a -> f a
queue2List :: Queue f => f a -> [a]
queue2List xs = case dequeue xs of
Nothing -> []
Just (y, ys) -> y : queue2List ys
list2Queue :: Queue f => [a] -> f a
list2Queue = foldl (\acc a -> enqueue acc a) emptyQueue
------------------------------------------------------------------
newtype ListQueue a = ListQueue { unListQueue :: [a] }
deriving (Show)
instance Functor ListQueue where
fmap f (ListQueue list) = ListQueue $ fmap f list
instance Queue ListQueue where
emptyQueue = ListQueue []
dequeue (ListQueue [ ]) = Nothing
dequeue (ListQueue (x : xs)) = Just (x, ListQueue xs)
enqueue (ListQueue xs) x = ListQueue $ go xs where
go [ ] = [x]
go (y : ys) = y : go ys
------------------------------------------------------------------
data PairedLists a = PairedLists [a] [a]
deriving (Show)
instance Functor PairedLists where
fmap f (PairedLists l r) = PairedLists (fmap f l) (fmap f r)
instance Queue PairedLists where
emptyQueue = PairedLists [] []
dequeue (PairedLists [] ys) = case List.reverse ys of
[] -> Nothing
x : xs -> Just (x, PairedLists xs [])
dequeue (PairedLists (x : xs) ys) = Just (x, PairedLists xs ys)
enqueue (PairedLists xs ys) a = PairedLists xs (a : ys)
------------------------------------------------------------------
naiveRotate :: [a] -> [a] -> [a]
naiveRotate xs ys = xs <> List.reverse ys
-- | rotate L R A
-- Invariant:
-- |R| = |L| + 1
rotate :: [a] -> [a] -> [a] -> [a]
rotate [ ] [y ] zs = y : zs
rotate (x : xs) (y : ys) zs = x : rotate xs ys (y : zs)
rotate _ _ _ = error "rotate: invariant violated"
-- | Dequeue is worst case O(log n)
data LazyPairedLists a = LazyPairedLists Int [a] Int [a]
deriving (Show)
sizeLPLQueue :: LazyPairedLists a -> Int
sizeLPLQueue (LazyPairedLists n _ m _) = n + m
makeLPLQueue :: Int -> [a] -> Int -> [a] -> LazyPairedLists a
makeLPLQueue sl l sr r
| sr <= sl = LazyPairedLists sl l sr r
| sr == sl + 1 = LazyPairedLists (sl + sr) (rotate l r []) 0 []
| otherwise = error "size invariant violated"
instance Queue LazyPairedLists where
emptyQueue = LazyPairedLists 0 [] 0 []
dequeue (LazyPairedLists 0 [] 0 []) = Nothing
dequeue (LazyPairedLists n (x : xs) m ys) = Just (x, makeLPLQueue (n - 1) xs m ys)
dequeue _ = error "dequeue failed"
enqueue (LazyPairedLists n xs m ys) a = makeLPLQueue n xs (m + 1) (a : ys)
instance IsList (LazyPairedLists a) where
type Item (LazyPairedLists a) = a
fromList = foldl enqueue emptyQueue
toList (LazyPairedLists _ xs _ ys) = naiveRotate xs ys
------------------------------------------------------------------
data RealTimeQueue a = RealTimeQueue [a] [a] [a]
deriving (Eq, Show)
makeRTQueue :: [a] -> [a] -> [a] -> RealTimeQueue a
makeRTQueue as bs cs = case cs of
[] -> let x = rotate as bs [] in RealTimeQueue x [] x
_ : xs -> RealTimeQueue as bs xs
instance Queue RealTimeQueue where
emptyQueue = RealTimeQueue [] [] []
dequeue (RealTimeQueue (x : xs) ys zs) = Just (x, makeRTQueue xs ys zs)
dequeue (RealTimeQueue [] _ _) = Nothing
enqueue (RealTimeQueue xs ys zs) a = makeRTQueue xs (a : ys) zs