dataTree a = Lf | Br !Int (Treea) a (Treea) deriving (Show)
size :: Tree a -> Int sizeLf = 0 size (Br s _ _ _) = s
br :: Tree a -> a -> Tree a -> Tree a br l x r = Br (1 + size l + size r) l x r
elem :: (Ord a) => a -> Tree a -> Bool elem _ Lf = False elem x (Br _ l y r) = case x `compare` y of LT -> elem x l GT -> elem x r EQ -> True
rank :: (Ord a) => a -> Tree a -> Int rank v = go 0 where go !acc Lf = acc go !acc (Br _ l x r) = case v `compare` x of LT -> go acc l _ -> go (acc + size l + 1) r
index :: Int -> Tree a -> a index = go where go !n t | size t < n = error "there is no enough elements" go !n (Br _ l x r) | n <= size l = go n l | n == size l + 1 = x | otherwise = go (n - 1 - size l) r
delta, alpha :: Int delta = 4 alpha = 2
balance :: Tree a -> a -> Tree a -> Tree a balance l x r | size l + size r <= 1 = br l x r | size r > size l * delta = rotateL l x r | size l > size r * delta = rotateR l x r | otherwise = br l x r
rotateL, rotateR :: Tree a -> a -> Tree a -> Tree a rotateL a x (Br _ b y c) | size b < size c * alpha = br (br a x b) y c | otherwise = case b ofBr _ l v r -> br (br a x l) v (br r y c) rotateR (Br _ a x b) y c | size b < size a * alpha = br a x (br b y c) | otherwise = case b ofBr _ l v r -> br (br a x l) v (br r y c)
insert :: (Ord a) => a -> Tree a -> Tree a insert v = ins where ins Lf = br Lf v Lf ins t@(Br _ l x r) = case v `compare` x of LT -> balance (ins l) x r GT -> balance l x (ins r) EQ -> t
delete :: (Ord a) => a -> Tree a -> Tree a delete v = del where del Lf = Lf del t@(Br _ l x r) = case v `compare` x of LT -> balance (del l) x r GT -> balance l x (del r) EQ -> join l r
join :: (Ord a) => Tree a -> Tree a -> Tree a joinLf t = t join t Lf = t join l r = let x = maxElem l in balance (delete x l) x r
maxElem :: (Ord a) => Tree a -> a maxElemLf = error "try to find max element in an empty tree" maxElem (Br _ _ x Lf) = x maxElem (Br _ _ _ r) = maxElem r instanceFoldableTreewhere foldMap f Lf = mempty foldMap f (Br _ l x r) = foldMap f l `mappend` f x `mappend` foldMap f r
toList :: Tree a -> [a] toList = foldr (:) []
fromList :: (Foldable t, Ord a) => t a -> Tree a fromList = foldr insert Lf
---
isBalanced :: Tree a -> Bool isBalancedLf = True isBalanced (Br _ l x r) | size l + size r <= 1 = True | otherwise = size l <= size r * delta && size r <= size l * delta && isBalanced l && isBalanced r