@ 131018.10 · fetching
current
module QC.SkewHeap
  ( Heap(..)
  , empty, isEmpty, insert, merge, peek, delete, heapify
  )
where

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

-- | A skew 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 h = merge h . single

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

-- | Implements the alternating left/right subtree merge which makes
-- this a skew tree.
merge :: Ord a => Heap a -> Heap a -> Heap a
merge Nil h = h
merge h Nil = h
merge n1 n2 = Node (merge (right s) b) (left s) (value s)
  where (s, b) = if value n1 <= value n2 then (n1, n2) else (n2, n1)