current commit
131018.2 · update
module QC.Heap
  ( Heap(..)
  , empty, isEmpty, insert, merge, peek, delete, heapify
  )
where

import Data.Monoid (Monoid, mappend, mempty)
import Text.Printf (printf)

-- | A boring functional min-heap.
data Heap a = Nil
            | Node { left :: Heap a, right :: Heap a, value :: a }
            deriving Eq

instance Ord a => Monoid (Heap a) where
  mempty = empty
  mappend = merge

instance Show a => Show (Heap a) where
  show = show' 0
    where show' d Nil = printf "%sNil\n" $ indent d
          show' d (Node l r v) = this ++ show' (d+1) l ++ show' (d+1) r
            where this = printf "%sNode %s\n" (indent d) (show v)

          indent d = concat $ replicate d "  "

empty :: Ord a => Heap a
empty = Nil

isEmpty :: Ord a => Heap a -> Bool
isEmpty Nil = True
isEmpty _   = False

single :: Ord a => a -> Heap a
single = Node Nil Nil

insert :: Ord a => Heap a -> a -> Heap a
insert Nil x = single x
insert n@(Node l r v) x =
  if x <= v then Node n Nil x else
    case (l, r) of
      (Nil, Nil) -> Node (single x) Nil v
      (Node{}, Nil) -> Node l (single x) v
      (Nil, Node{}) -> Node (single x) r v
      (Node _ _ lv, Node _ _ rv) ->
        if lv <= rv then Node (insert l x) r v else Node l (insert r x) v

peek :: Ord a => Heap a -> a
peek Nil = error "cannot peek empty heap"
peek (Node _ _ v) = v

delete :: Ord a => Heap a -> Heap a
delete Nil = Nil
delete (Node l r v) = merge l r

heapify :: Ord a => [a] -> Heap a
heapify = foldl insert empty

merge :: Ord a => Heap a -> Heap a -> Heap a
merge h Nil = h
merge h (Node l r v) = insert (merge (merge h l) r) v