packages feed

swish-0.2.1: Swish/HaskellRDF/Sort/CartesianTree.lhs

%- - - - - - - - - - - - - - - -=  - - - - - - - - - - - - - - - - - - - - - -
\subsection{Cartesian trees}
%- - - - - - - - - - - - - - - -=  - - - - - - - - - - - - - - - - - - - - - -

%align

> module Swish.HaskellRDF.Sort.CartesianTree 
> where

%align 33

> data BinTree a		=  Leaf
>				|  Node (BinTree a) a (BinTree a)
>				   deriving (Show)

Constructing a cartesian tree in linear time.

> data Spine a			=  Nil
>				|  Cons a (BinTree a) (Spine a)

> up				:: BinTree a -> Spine a -> BinTree a
> up l Nil			=  l
> up l (Cons a r s)		=  up (Node l a r) s

> cartesianTree			:: (Ord a) => [a] -> BinTree a
> cartesianTree			=  cartesianTreeBy (<=)
>
> cartesianTreeBy (<=)		=  up Leaf . foldr (\a s -> cons a Leaf s) Nil
>   where cons a t Nil		=  Cons a t Nil
>         cons a t s@(Cons a' t' s')
>             | a <= a'		=  cons a (Node t a' t') s'
>             | otherwise	=  Cons a t s

|cartesianTree [5, 8, 2, 3, 7, 4, 10, 0]|

\NB The obvious approaches (top-down and bottom-up) both lead to
$\Theta(n\log n)$ algorithms. For curiosity here is the top-down
variant of |meld|.

> meld				:: (Ord a) => BinTree a -> BinTree a -> BinTree a
> meld Leaf u			=  u
> meld t Leaf			=  t
> meld t@(Node l a r) u@(Node l' a' r')
>     | a <= a'			=  Node l a (meld r u)
>     | otherwise		=  Node (meld t l') a' r'

Note that the relative order of elements is preserved. The bottom-up
variants of cartesian trees are called \technical{pagodas}.