(* file: sort.ml * author: Bob Muller * * CS1103 Computer Science I Honors * * Three algorithms for sorting lists of elements. * * * Insertionsort ******************************************************** * * insert : 'a -> 'a list -> 'a list * * The call (insert x xs) assumes that xs is in order. Requires on the * order of N^2 units of work. It returns the ordered list resulting * from inserting x. *) let rec insert n ns = match ns with | [] -> [n] | m :: ms -> (match n < m with | true -> n :: ns | false -> m :: insert n ms) let insertionSort ns = let rec again ms sorted = match ms with | [] -> sorted | n :: ns -> again ns (insert n sorted) in again ns [] (* Quicksort ******************************************************** * * Tony Hoare ~1960, O(N log N) on average but O(N^2) in the worst case. * * partition : 'a -> 'a list -> ('a list * 'a list) * * The call (partition pivot ns) returns the pair of lists (less, greater). *) let rec partition pivot ns = match ns with | [] -> ([], []) | m :: ms -> let (less, greater) = partition pivot ms in match m < pivot with | true -> (m :: less, greater) | false -> (less, m :: greater) (* quicksort : 'a list -> 'a list *) let rec quicksort ns = match ns with | [] | [_] -> ns | pivot :: ns -> let (smaller, larger) = partition pivot ns in (quicksort smaller) @ [pivot] @ (quicksort larger) (* Mergesort ******************************************************** * * John von Neumann, O(N log N) on average AND in the worst case. * * split : 'a list -> ('a list * 'a list) * * The call (split xs) returns the pair of lists (left, right). *) let split xs = let n = List.length xs in let rec split' m xs = match (m = 0, xs) with | (true, _) -> ([], xs) | (false, y :: ys) -> let (left, right) = split' (m - 1) ys in (y :: left, right) in split' (n / 2) xs let rec merge xs ys = match (xs, ys) with | ([], _) -> ys | (_, []) -> xs | (x :: xs', y :: ys') -> (match x < y with | true -> x :: (merge xs' ys) | false -> y :: (merge xs ys')) let rec mergesort ns = match List.length ns < 2 with | true -> ns | false -> let (left, right) = split ns in merge (mergesort left) (mergesort right)