Skip to main content
Commonmark migration
Source Link

#Book's implementation quicksort :: ( Ord a ) = > [ a ] -> [ a ] quicksort [] = [] quicksort ( x : xs ) = let smallerSorted = quicksort [ a | a <- xs , a <= x ] biggerSorted = quicksort [ a | a <- xs , a > x ] in smallerSorted ++ [ x ] ++ biggerSorted

Book's implementation

quicksort :: ( Ord a ) = > [ a ] -> [ a ]
quicksort [] = []
quicksort ( x : xs ) =
    let smallerSorted = quicksort [ a | a <- xs , a <= x ]
        biggerSorted = quicksort [ a | a <- xs , a > x ]
    in smallerSorted ++ [ x ] ++ biggerSorted

#My implementation

My implementation

#Book's implementation quicksort :: ( Ord a ) = > [ a ] -> [ a ] quicksort [] = [] quicksort ( x : xs ) = let smallerSorted = quicksort [ a | a <- xs , a <= x ] biggerSorted = quicksort [ a | a <- xs , a > x ] in smallerSorted ++ [ x ] ++ biggerSorted

#My implementation

Book's implementation

quicksort :: ( Ord a ) = > [ a ] -> [ a ]
quicksort [] = []
quicksort ( x : xs ) =
    let smallerSorted = quicksort [ a | a <- xs , a <= x ]
        biggerSorted = quicksort [ a | a <- xs , a > x ]
    in smallerSorted ++ [ x ] ++ biggerSorted

My implementation

Source Link
LRDPRDX
  • 831
  • 5
  • 15

The quicksort algorithm in Haskell

I am learning Haskell programming language mainly from this source. And there I have encouraged with "an elegant" realization of the quicksort sorting algorithm (the Quick, sort! section). Here it is:

#Book's implementation quicksort :: ( Ord a ) = > [ a ] -> [ a ] quicksort [] = [] quicksort ( x : xs ) = let smallerSorted = quicksort [ a | a <- xs , a <= x ] biggerSorted = quicksort [ a | a <- xs , a > x ] in smallerSorted ++ [ x ] ++ biggerSorted

The problem with this implementation (as I think) is doubled number of comparisons inside the let binding every time. Isn't the fact that those of a's that already in the smallerSorted list cannot be in the biggerSorted list, so we don't need to compare x with them anymore.

In order to "improve" the above approach I have written my own implementation, where I use auxiliary local function split that splits a list into two parts: less than (or equal to) x and greater than x.

#My implementation

quick_sort :: (Ord a) => [a] -> [a]
quick_sort []       = [] --edge condition 
quick_sort (x : xs) =    --general condition
    let (lt, gt) = split x xs
    in  (quick_sort lt) ++ [x] ++ (quick_sort gt) 
    where
        --split function is used to split a list
        --into two sublists: one for elements
        --less or equal (lt) than some value - x
        --and one for those that greater (gt) than x
        --NOTE: split function is also recursive
        split x [] = ([], []) --edge condition
        split x (h : hs)      --general condition
            | h <= x    =
                let (lt, gt) = split x hs
                in ( (h : lt), gt )
            | otherwise =
                let (lt, gt) = split x hs
                in ( lt, (h : gt) )

P.S. For a while I am not able to compare two approaches, but on the worst cases (when list to sort is already sorted) it seems that my implementation is a bit slower.