okasaki

Okasaki's Purely Functional Data Structures
Log | Files | Refs | LICENSE

commit b39631fa0a5252fe6659125116260ef7790456f0
parent 3e3ee09745af8c15873103c399f2cc9a9c402763
Author: Jared Tobin <jared@jtobin.ca>
Date:   Thu, 20 Nov 2014 23:31:16 +1300

Some work on leftist heaps.

Diffstat:
AFiniteMap.hs | 39+++++++++++++++++++++++++++++++++++++++
ALeftistHeap.hs | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MTree.hs | 33---------------------------------
3 files changed, 112 insertions(+), 33 deletions(-)

diff --git a/FiniteMap.hs b/FiniteMap.hs @@ -0,0 +1,39 @@ +{-# OPTIONS_GHC -Wall #-} + +module FiniteMap where + +import Tree + +-- exercise 2.6 (finite map using tree) +newtype Bin k v = Bin (k, v) deriving Show + +instance Eq k => Eq (Bin k v) where + Bin (k0, _) == Bin (k1, _) = k0 == k1 + +instance Ord k => Ord (Bin k v) where + compare (Bin (k0, _)) (Bin (k1, _)) = compare k0 k1 + +newtype FiniteMap k v = FiniteMap (Tree (Bin k v)) deriving (Eq, Show) + +emptyMap :: FiniteMap k v +emptyMap = FiniteMap Leaf + +bind :: Ord k => k -> v -> FiniteMap k v -> FiniteMap k v +bind k v (FiniteMap m) = FiniteMap (insert' (Bin (k, v)) m) where + insert' x Leaf = Node Leaf x Leaf + insert' x (Node l e r) = case compare x e of + EQ -> Node l x r + LT -> Node (insert' x l) e r + GT -> Node l e (insert' x r) + +lookup :: Ord k => k -> FiniteMap k v -> Maybe v +lookup k (FiniteMap m) = lookup' m where + lookup' Leaf = Nothing + lookup' (Node l (Bin (key, v)) r) = case compare k key of + EQ -> Just v + LT -> lookup' l + GT -> lookup' r + +testMap :: FiniteMap Char Int +testMap = bind 'b' 2 (bind 'a' 1 emptyMap) + diff --git a/LeftistHeap.hs b/LeftistHeap.hs @@ -0,0 +1,73 @@ +{-# OPTIONS_GHC -Wall #-} + +module LeftistHeap where + +import Control.Arrow + +data Heap a = Leaf | Node Int a (Heap a) (Heap a) deriving (Eq, Show) + +empty :: Heap a +empty = Leaf + +isEmpty :: Heap a -> Bool +isEmpty Leaf = True +isEmpty _ = False + +merge :: Ord a => Heap a -> Heap a -> Heap a +merge h Leaf = h +merge Leaf h = h +merge h0@(Node _ e0 l0 r0) h1@(Node _ e1 l1 r1) + | e0 <= e1 = create e0 l0 (merge r0 h1) + | otherwise = create e1 l1 (merge h0 r1) + +rank :: Heap a -> Int +rank Leaf = 0 +rank (Node r _ _ _) = r + +create :: a -> Heap a -> Heap a -> Heap a +create e l r + | rank l >= rank r = Node (succ (rank r)) e l r + | otherwise = Node (succ (rank l)) e r l + +singleton :: Ord a => a -> Heap a +singleton e = Node 1 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 + +-- exercise 3.1 (prove right-spine contains at most floor(log(n + 1)) elements) +-- - binary tree; observe that rightmost-weighted binary tree obeying leftist +-- property is balanced. +-- - right spine length is maximized in balanced case. +-- - tree has depth floor(log(n + 1)) in balanced case. +-- - right spine has at most floor(log(n + 1)) elements. + +-- exercise 3.2 (define insert directly rather than by merge) +altInsert :: Ord a => a -> Heap a -> Heap a +altInsert e Leaf = singleton e +altInsert e0 (Node _ e1 l r) + | rank l0 >= rank r0 = Node (succ (rank r0)) top l0 r0 + | otherwise = Node (succ (rank l0)) top r0 l0 + where + (l0, r0) = cascadeInsert bottom (l, r) + (top, bottom) + | e0 <= e1 = (e0, e1) + | otherwise = (e1, e0) + +cascadeInsert :: Ord a => a -> (Heap a, Heap a) -> (Heap a, Heap a) +cascadeInsert e (h, Leaf) = (h, singleton e) +cascadeInsert e (Leaf, h) = (h, singleton e) +cascadeInsert e hs@(Node _ e0 _ _, Node _ e1 _ _) = f (altInsert e) hs where + f = if e0 > e1 then first else second + diff --git a/Tree.hs b/Tree.hs @@ -79,36 +79,3 @@ completeSize x n r = completeSize x (n `quot` 2 - 1) in Node l x r --- exercise 2.6 (finite map using tree) -newtype Bin k v = Bin (k, v) deriving Show - -instance Eq k => Eq (Bin k v) where - Bin (k0, _) == Bin (k1, _) = k0 == k1 - -instance Ord k => Ord (Bin k v) where - compare (Bin (k0, _)) (Bin (k1, _)) = compare k0 k1 - -newtype FiniteMap k v = FiniteMap (Tree (Bin k v)) deriving (Eq, Show) - -emptyMap :: FiniteMap k v -emptyMap = FiniteMap Leaf - -bind :: Ord k => k -> v -> FiniteMap k v -> FiniteMap k v -bind k v (FiniteMap m) = FiniteMap (insert' (Bin (k, v)) m) where - insert' x Leaf = Node Leaf x Leaf - insert' x (Node l e r) = case compare x e of - EQ -> Node l x r - LT -> Node (insert' x l) e r - GT -> Node l e (insert' x r) - -lookup :: Ord k => k -> FiniteMap k v -> Maybe v -lookup k (FiniteMap m) = lookup' m where - lookup' Leaf = Nothing - lookup' (Node l (Bin (key, v)) r) = case compare k key of - EQ -> Just v - LT -> lookup' l - GT -> lookup' r - -testMap :: FiniteMap Char Int -testMap = bind 'b' 2 (bind 'a' 1 emptyMap) -