{-# LANGUAGE NoMonomorphismRestriction #-}
data Map k a = Tip | Bin Size k a (Map k a) (Map k a)
size t
= case t of
Tip -> 0
Bin sz _ _ _ _ -> sz
----------------------------------------------------------------
-- basic rotations
singleL, singleR :: a -> b -> Map a b -> Map a b -> Map a b
singleL k1 x1 t1 (Bin _ k2 x2 t2 t3) = bin k2 x2 (bin k1 x1 t1 t2) t3
singleR k1 x1 (Bin _ k2 x2 t1 t2) t3 = bin k2 x2 t1 (bin k1 x1 t2 t3)
doubleL, doubleR :: a -> b -> Map a b -> Map a b -> Map a b
doubleL k1 x1 t1 (Bin _ k2 x2 (Bin _ k3 x3 t2 t3) t4) = bin k3 x3 (bin k1 x1 t1 t2) (bin k2 x2 t3 t4)
doubleR k1 x1 (Bin _ k2 x2 t1 (Bin _ k3 x3 t2 t3)) t4 = bin k3 x3 (bin k2 x2 t1 t2) (bin k1 x1 t3 t4)
----------------------------------------------------------------
bin :: k -> a -> Map k a -> Map k a -> Map k a
bin k x l r
= Bin (size l + size r + 1) k x l r
singleton :: k -> a -> Map k a
singleton k x
= Bin 1 k x Tip Tip
isBalanced
:: Map k a
-> Map k a
-> BoolisBalanced a b = 3 * x >= y
where
x = size a + 1
y = size b + 1
isSingle
:: Map k a
-> Map k a
-> BoolisSingle a b = z < 2 * w
where
z = size a + 1
w = size b + 1
----------------------------------------------------------------
balanceL :: k -> a -> Map k a -> Map k a -> Map k a
balanceL k x l r
| isBalanced l r = bin k x l r
balanceR :: k -> a -> Map k a -> Map k a -> Map k a
balanceR k x l r
| isBalanced r l = bin k x l r
balance :: k -> a -> Map k a -> Map k a -> Map k a
balance k x l r
| isBalanced l r && isBalanced r l = bin k x l r
| size l > size r = rotateR k x l r
----------------------------------------------------------------
rotateL :: a -> b -> Map a b -> Map a b -> Map a b
rotateL k x l r@(Bin _ _ _ rl rr)
| isSingle rl rr = singleL k x l r
rotateR :: a -> b -> Map a b -> Map a b -> Map a b
rotateR k x l@(Bin _ _ _ ll lr) r
| isSingle lr ll = singleR k x l r
----------------------------------------------------------------
join
:: Ord k
=> k
-> a
-> Map k a
-> Map k a
-> Map k a
join kx x Tip r = insertMin kx x r
join kx x l Tip = insertMax kx x l
join kx x l@(Bin _ ky y ly ry) r@(Bin _ kz z lz rz)
| bal1 && bal2 = bin kx x l r
| bal1 = balanceL ky y ly (join kx x ry r)
| otherwise = balanceR kz z
(join kx x l lz
) rz
where
bal1 = isBalanced l r
bal2 = isBalanced r l
merge :: Map k a -> Map k a -> Map k a
merge Tip r = r
merge l Tip = l
merge l@(Bin _ kx x lx rx) r@(Bin _ ky y ly ry)
| bal1 && bal2 = glue l r
| bal1 = balanceL kx x lx (merge rx r)
where
bal1 = isBalanced l r
bal2 = isBalanced r l
----------------------------------------------------------------
insertMax,insertMin :: k -> a -> Map k a -> Map k a
insertMax kx x t
= case t of
Tip -> singleton kx x
Bin _ ky y l r
-> balanceL ky y l (insertMax kx x r)
insertMin kx x t
= case t of
Tip -> singleton kx x
Bin _ ky y l r
-> balanceR ky y (insertMin kx x l) r
----------------------------------------------------------------
glue :: Map k a -> Map k a -> Map k a
glue Tip r = r
glue l Tip = l
glue l r
| size l > size r = let ((km,m),l') = deleteFindMax l in balanceL km m l' r
| otherwise = let ((km
,m
),r
') = deleteFindMin r in balanceR km m l r'
-- | /O(log n)/. Delete and find the minimal element.
--
-- > deleteFindMin (fromList [(5,"a"), (3,"b"), (10,"c")]) == ((3,"b"), fromList[(5,"a"), (10,"c")])
-- > deleteFindMin Error: can not return the minimal element of an empty map
deleteFindMin :: Map k a -> ((k,a),Map k a)
deleteFindMin t
= case t of
Bin _ k x Tip r -> ((k,x),r)
Bin _ k x l r -> let (km,l') = deleteFindMin l in (km,balance k x l' r)
Tip
-> (error "Map.deleteFindMin: can not return the minimal element of an empty map", Tip
)
-- | /O(log n)/. Delete and find the maximal element.
--
-- > deleteFindMax (fromList [(5,"a"), (3,"b"), (10,"c")]) == ((10,"c"), fromList [(3,"b"), (5,"a")])
-- > deleteFindMax empty Error: can not return the maximal element of an empty map
deleteFindMax :: Map k a -> ((k,a),Map k a)
deleteFindMax t
= case t of
Bin _ k x l Tip -> ((k,x),l)
Bin _ k x l r -> let (km,r') = deleteFindMax r in (km,balance k x l r')
Tip
-> (error "Map.deleteFindMax: can not return the maximal element of an empty map", Tip
)
----------------------------------------------------------------
balanced
:: Map k a
-> Boolbalanced Tip = True
balanced (Bin _ _ _ l r) = isBalanced l r && isBalanced r l && balanced l && balanced r
push k a = glue a $ singleton k k