Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quicksort in F# - syntax question

Tags:

f#

quicksort

I have a simple f# quick sort function defined as:

let rec qsort(xs:List<int>) =

let smaller = xs |> List.filter(fun e -> e < xs.Head)
let larger = xs |> List.filter(fun e -> e > xs.Head)
match xs with
| [] -> []
| _ -> qsort(smaller)@[xs.Head]@qsort(larger)

Is there a way in f# to write it more like Haskell:

qsort       :: [Int] -> [Int]
qsort []     = []
qsort (x:xs) =
qsort smaller ++ [x] ++ qsort larger
where
  smaller = [a | a <- xs, a <= x]
  larger  = [b | b <- xs, b >= x]

I know the f# algorithm is missing a <= and >=. The question is more about syntax/readibility.

Thanks.

like image 813
Neerav Avatar asked Dec 30 '09 19:12

Neerav


People also ask

Is quick sort in-place?

Quicksort is an in-place sorting algorithm. Developed by British computer scientist Tony Hoare in 1959 and published in 1961, it is still a commonly used algorithm for sorting. When implemented well, it can be somewhat faster than merge sort and about two or three times faster than heapsort.

What is quick sort function?

Quicksort: Quick sort is an Divide Conquer algorithm and the fastest sorting algorithm. In quick sort, it creates two empty arrays to hold elements less than the pivot element and the element greater than the pivot element and then recursively sort the sub-arrays.

Why is quicksort O N 2?

The worst case time complexity of a typical implementation of QuickSort is O(n2). The worst case occurs when the picked pivot is always an extreme (smallest or largest) element. This happens when input array is sorted or reverse sorted and either first or last element is picked as pivot.


1 Answers

This is the most 'Haskellian' way I can think of, the only thing missing is being able to declare smaller/larger as a 'where' clause:

let rec qsort:int list -> int list = function
    | [] -> []
    | x::xs -> let smaller = [for a in xs do if a<=x then yield a]
               let larger =  [for b in xs do if b>x then yield b]
               qsort smaller @ [x] @ qsort larger

I know it's not part of your question, but I'd use List.partition to split the list in smaller/larger in a single pass:

let rec qsort = function
    | [] -> []
    | x::xs -> let smaller,larger = List.partition (fun y -> y<=x) xs
               qsort smaller @ [x] @ qsort larger
like image 64
cfern Avatar answered Oct 30 '22 08:10

cfern