commit a1e4d2e8a9d3b7476aad8ab80152cae96624ecf8
parent 2cf32a073a1b260c7c9f29b245b06339296c68b7
Author: Jared Tobin <jared@jtobin.ca>
Date: Sat, 22 Nov 2014 21:42:21 +1300
Moar heap work.
Diffstat:
3 files changed, 141 insertions(+), 3 deletions(-)
diff --git a/BinomialHeap.hs b/BinomialHeap.hs
@@ -2,10 +2,16 @@
module BinomialHeap where
-data Tree a = Node Int a [Tree a]
+data Tree a = Node Int a [Tree a] deriving Show
type Heap a = [Tree a]
+empty :: Heap a
+empty = []
+
+isEmpty :: Heap a -> Bool
+isEmpty = null
+
link :: Ord a => Tree a -> Tree a -> Tree a
link t0@(Node r x0 c0) t1@(Node _ x1 c1)
| x0 <= x1 = Node (succ r) x0 (t1 : c0)
@@ -54,3 +60,62 @@ deleteMin ts = case removeMinTree ts of
Nothing -> []
Just (Node _ _ ts0, ts1) -> merge (reverse ts0) ts1
+fromList :: Ord a => [a] -> Heap a
+fromList = foldr insert empty
+
+-- exercise 3.5 (findMin without call to removeMinTree)
+altFindMin :: Ord a => Heap a -> Maybe a
+altFindMin [] = Nothing
+altFindMin [t] = return $ root t
+altFindMin (Node _ e _:ts) = do
+ alt <- altFindMin ts
+ return $
+ if e < alt
+ then e
+ else alt
+
+-- exercise 3.7 (O(1) min in ocaml functor style)
+class Heaplike h where
+ hEmpty :: h a
+ hIsEmpty :: h a -> Bool
+ hInsert :: Ord a => a -> h a -> h a
+ hFindMin :: Ord a => h a -> Maybe a
+ hDeleteMin :: Ord a => h a -> h a
+
+ hFromList :: Ord a => [a] -> h a
+ hFromList = foldr hInsert hEmpty
+
+data ExplicitMinHeap h a = E | NE a (h a) deriving Show
+
+instance Heaplike h => Heaplike (ExplicitMinHeap h) where
+ hEmpty = E
+
+ hIsEmpty E = True
+ hIsEmpty _ = False
+
+ hInsert e E = NE e (hInsert e hEmpty)
+ hInsert e (NE m h) = NE (min e m) (hInsert e h)
+
+ hFindMin E = Nothing
+ hFindMin (NE m _) = Just m
+
+ hDeleteMin E = hEmpty
+ hDeleteMin (NE m0 h) =
+ let smaller = hDeleteMin h
+ in case hFindMin smaller of
+ Nothing -> NE m0 smaller
+ Just m1 -> NE (min m0 m1) smaller
+
+-- example
+newtype BinomialHeap a = BinomialHeap { unwrap :: Heap a } deriving Show
+
+instance Heaplike BinomialHeap where
+ hEmpty = BinomialHeap empty
+ hIsEmpty = isEmpty . unwrap
+ hInsert e (BinomialHeap h) = BinomialHeap $ insert e h
+ hFindMin (BinomialHeap h) = findMin h
+ hDeleteMin (BinomialHeap h) = BinomialHeap $ deleteMin h
+
+altFromList :: Ord a => [a] -> ExplicitMinHeap BinomialHeap a
+altFromList = hFromList
+
diff --git a/UnrankedBinomialHeap.hs b/UnrankedBinomialHeap.hs
@@ -0,0 +1,65 @@
+{-# OPTIONS_GHC -Wall #-}
+
+module UnrankedBinomialHeap where
+
+-- exercise 3.6 (alternate-rank representation of binomial heaps)
+data Tree a = Node a [Tree a] deriving Show
+
+type Heap a = [(Int, Tree a)]
+
+empty :: Heap a
+empty = []
+
+isEmpty :: Heap a -> Bool
+isEmpty = null
+
+link :: Ord a => (Int, Tree a) -> (Int, Tree a) -> (Int, Tree a)
+link (r, t0@(Node x0 c0)) (_, t1@(Node x1 c1))
+ | x0 <= x1 = (succ r, Node x0 (t1 : c0))
+ | otherwise = (succ r, Node x1 (t0 : c1))
+
+root :: Tree a -> a
+root (Node x _) = x
+
+insertTree :: Ord a => (Int, Tree a) -> Heap a -> Heap a
+insertTree p [] = [p]
+insertTree p0@(r0, _) ts@(p1@(r1, _):trees)
+ | r0 < r1 = p0 : ts
+ | otherwise = insertTree (link p0 p1) trees
+
+insert :: Ord a => a -> Heap a -> Heap a
+insert x = insertTree (0, Node x [])
+
+merge :: Ord a => Heap a -> Heap a -> Heap a
+merge ts [] = ts
+merge [] ts = ts
+merge ts0@(tree0:trees0) ts1@(tree1:trees1)
+ | fst tree0 < fst tree1 = tree0 : merge trees0 ts1
+ | fst tree1 < fst tree0 = tree1 : merge ts0 trees1
+ | otherwise = insertTree (link tree0 tree1) (merge trees0 trees1)
+
+removeMinTree :: Ord a => Heap a -> Maybe ((Int, Tree a), Heap a)
+removeMinTree [] = Nothing
+removeMinTree [p] = return (p, [])
+removeMinTree (p0@(_, t):ts) = do
+ (p1@(_, tree), trees) <- removeMinTree ts
+ return $
+ if root t < root tree
+ then (p0, ts)
+ else (p1, p0:trees)
+
+findMin :: Ord a => Heap a -> Maybe a
+findMin ts = do
+ ((_, t), _) <- removeMinTree ts
+ return $ root t
+
+deleteMin :: Ord a => Heap a -> Heap a
+deleteMin ts = case removeMinTree ts of
+ Nothing -> []
+ Just ((r, Node _ ts0), ts1) ->
+ let lesser = zip (repeat (pred r)) (reverse ts0)
+ in merge lesser ts1
+
+fromList :: Ord a => [a] -> Heap a
+fromList = foldr insert empty
+
diff --git a/WeightBiasedLeftistHeap.hs b/WeightBiasedLeftistHeap.hs
@@ -41,6 +41,14 @@ singleton e = Node e Leaf Leaf
insert :: Ord a => a -> Heap a -> Heap a
insert e = merge (singleton e)
+findMin :: Heap a -> Maybe a
+findMin Leaf = Nothing
+findMin (Node e _ _) = return e
+
+deleteMin :: Ord a => Heap a -> Heap a
+deleteMin Leaf = Leaf
+deleteMin (Node _ l r) = merge l r
+
fromList :: Ord a => [a] -> Heap a
fromList = foldr insert empty
@@ -58,6 +66,6 @@ altMerge h0@(Node e0 l0 r0) h1@(Node e1 l1 r1) = Node e l r where
| otherwise = second (`altMerge` h) branches
-- exercise 3.4d (advantages of altMerge)
--- - lazy environment ?
--- - concurrent environment ?
+-- - lazy environment (no buildup of thunks?)
+-- - concurrent environment (more opportunity for concurrency?)