packages feed

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

%-------------------------------=  --------------------------------------------
\chapter{Splay sort}
%-------------------------------=  --------------------------------------------

%align

> module Swish.HaskellRDF.Sort.SplaySort 
> where
> import Swish.HaskellRDF.Sort.LibBase

%align 33

Sorting on the basis on splay trees has most of the desired features:
is asymptotically optimal, stable and it adapts to the input. In fact,
it has been conjectured \cite{MEP96Spl} that it is optimatically
adaptive to all accepted measures of presortedness. The following code
is due to Chris Okasaki \cite[p.~46]{Oka98Pur}.

> data SplayTree a 		=  Empty
>				|  Bin (SplayTree a) a (SplayTree a)
>
> insertBy			:: Rel a -> a -> SplayTree a -> SplayTree a
> insertBy (<=) a t		=  Bin lt a ge
>    where (lt, ge)		=  partBy (<=) a t

\NB |lt| means \U{l}ess \U{t}han and |ge| means \U{g}reater \U{e}qual.

> partBy			:: Rel a -> a -> SplayTree a -> (SplayTree a, SplayTree a)
> partBy (<=) k Empty		=  (Empty, Empty)
> partBy (<=) k t@(Bin l a r)
>    | k <= a			=  case l of
>         Empty			-> (Empty, t)
>         Bin ll la lr
>             | k <= la		-> let (lt, ge) = partBy (<=) k ll in (lt, Bin ge la (Bin lr a r))
>             | otherwise	-> let (lt, ge) = partBy (<=) k lr in (Bin ll la lt, Bin ge a r)
>     | otherwise		=  case r of
>         Empty			-> (t, Empty)
>         Bin rl ra rr
>             | k <= ra		-> let (lt, ge) =  partBy (<=) k rl in (Bin l a lt, Bin ge ra rr)
>             | otherwise	-> let (lt, ge) =  partBy (<=) k rr in (Bin (Bin l a rl) ra lt, ge)

\NB Throughout the library great care is taken to ensure that the
relative order of equal elements is preserved. This is most easily
accomplished if the order of the arguments to a function reflects the
original order within the input. Consider, for example, the definition
of |insertBy|: on the left hand side |a| appears before |t|, on the
right hand side |a| appears before |ge| which may contain elements
equal to |a|. Thus, the relative order of equal elements is preserved.
That said, it is probably clear which we use |foldr| instead of |foldl|
for building trees.

> inorder			:: SplayTree a -> [a]
> inorder t			=  traverse t []
>     where
>     traverse Empty x		=  x
>     traverse (Bin l a r) x	=  traverse l (a : traverse r x)
>
> splaySort			:: (Ord a) => [a] -> [a]
> splaySort			=  splaySortBy (<=)
>
> splaySortBy			:: Rel a -> [a] -> [a]
> splaySortBy (<=)		=  inorder . foldr (insertBy (<=)) Empty