{-| Leftist Heap - the fun of programming -} module Data.Heap.Leftist ( -- * Data structures Leftist(..) , Rank -- * Creating heaps , empty , singleton , insert , fromList -- * Converting to a list , toList -- * Deleting , deleteMin -- * Checking heaps , null -- * Helper functions , merge , minimum , valid , heapSort ) where import Control.Applicative hiding (empty) import Data.List (foldl', unfoldr) import Data.Maybe import Prelude hiding (minimum, maximum, null) ---------------------------------------------------------------- data Leftist a = Leaf | Node Rank (Leftist a) a (Leftist a) deriving Show instance (Eq a, Ord a) => Eq (Leftist a) where h1 == h2 = heapSort h1 == heapSort h2 type Rank = Int ---------------------------------------------------------------- rank :: Leftist a -> Rank rank Leaf = 0 rank (Node v _ _ _) = v ---------------------------------------------------------------- {-| Empty heap. -} empty :: Leftist a empty = Leaf {-| See if the heap is empty. >>> Data.Heap.Leftist.null empty True >>> Data.Heap.Leftist.null (singleton 1) False -} null :: Leftist t -> Bool null Leaf = True null (Node _ _ _ _) = False {-| Singleton heap. -} singleton :: a -> Leftist a singleton x = Node 1 Leaf x Leaf ---------------------------------------------------------------- {-| Insertion. >>> insert 7 (fromList [5,3]) == fromList [3,5,7] True >>> insert 5 empty == singleton 5 True -} insert :: Ord a => a -> Leftist a -> Leftist a insert x t = merge (singleton x) t ---------------------------------------------------------------- {-| Creating a heap from a list. >>> empty == fromList [] True >>> singleton 'a' == fromList ['a'] True >>> fromList [5,3] == fromList [5,3] True -} fromList :: Ord a => [a] -> Leftist a fromList = foldl' (flip insert) empty ---------------------------------------------------------------- {-| Creating a list from a heap. O(N) >>> let xs = [5,3,5] >>> length (toList (fromList xs)) == length xs True >>> toList empty [] -} toList :: Leftist a -> [a] toList t = inorder t [] where inorder Leaf xs = xs inorder (Node _ l x r) xs = inorder l (x : inorder r xs) ---------------------------------------------------------------- {-| Finding the minimum element. >>> minimum (fromList [3,5,1]) Just 1 >>> minimum empty Nothing -} minimum :: Leftist a -> Maybe a minimum Leaf = Nothing minimum (Node _ _ x _) = Just x ---------------------------------------------------------------- {-| Deleting the minimum element. >>> deleteMin (fromList [5,3,7]) == fromList [5,7] True >>> deleteMin empty == empty True -} deleteMin :: Ord a => Leftist a -> Leftist a deleteMin Leaf = Leaf deleteMin (Node _ l _ r) = merge l r deleteMin2 :: Ord a => Leftist a -> Maybe (a, Leftist a) deleteMin2 Leaf = Nothing deleteMin2 h = (\m -> (m, deleteMin h)) <$> minimum h ---------------------------------------------------------------- {-| Merging two heaps >>> merge (fromList [5,3]) (fromList [5,7]) == fromList [3,5,5,7] True -} merge :: Ord a => Leftist a -> Leftist a -> Leftist a merge t1 Leaf = t1 merge Leaf t2 = t2 merge t1@(Node _ l1 x1 r1) t2@(Node _ l2 x2 r2) | x1 <= x2 = join l1 x1 (merge r1 t2) | otherwise = join l2 x2 (merge t1 r2) join :: Ord a => Leftist a -> a -> Leftist a -> Leftist a join t1 x t2 | rank t1 >= rank t2 = Node (rank t2 + 1) t1 x t2 | otherwise = Node (rank t1 + 1) t2 x t1 ---------------------------------------------------------------- -- Basic operations ---------------------------------------------------------------- {-| Checking validity of a heap. -} valid :: Ord a => Leftist a -> Bool valid t = isOrdered (heapSort t) heapSort :: Ord a => Leftist a -> [a] heapSort t = unfoldr deleteMin2 t isOrdered :: Ord a => [a] -> Bool isOrdered [] = True isOrdered [_] = True isOrdered (x:y:xys) = x <= y && isOrdered (y:xys) -- allowing duplicated keys