Algorithms: 6. Quick Sort

Algorithms: 6. Quick Sort

Mar 20, 2022
programming, go, algorithms, generics

Introduction #

The Quick Sort algorithm uses what is known as a divide and conquor technique. It revolves around the idea of choosing a particular element in the array and then doing what is called pivoting around that. Essentially, all the elements less than the pivot go into the left hand array, all the elements greater than the pivot go into the right had array. The pivot itself can be choosen in different ways. It can be:

  • the first element in the array
  • the last element in the array
  • a random element in the array
  • the median index in the array

Let’s take this array - [410,821,551,51,638]

Pivots in this case are 0 and 1.

flowchart TD; A([410,821,551,51,638]) --> B([51]); A([410,821,551,51,638]) --> C([821,551,638]); C([821,551,638]) --> F([551,638]); C([821,551,638]) --> G([-]); F([551,638]) --> H([551]); F([551,638]) --> I([638]); H([551]) --> J([551]); H([551]) --> K([-]); I([638]) --> L([638]); I([638]) --> M([-]); B([51]) --> D([51]); B([51]) --> E([-]); classDef greenClass fill:#9f6;

Solution #

package main

import (
    "flag"
    "fmt"
    "math/rand"

    "golang.org/x/exp/constraints"
)

func quickSort[T constraints.Ordered](array []T) []T {

    if len(array) < 2 {
        return array
    }

    left, right := 0, len(array)-1

    pivot := rand.Int() % len(array)

    tmp := array[pivot]
    array[pivot] = array[right]
    array[right] = tmp

    for i, _ := range array {
        if array[i] < array[right] {
            tmp = array[left]
            array[left] = array[i]
            array[i] = tmp
            left++
        }
    }

    tmp = array[left]
    array[left] = array[right]
    array[right] = tmp

    quickSort(array[:left])
    quickSort(array[left+1:])

    return array
}

func randomString(n int) string {

    var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

    s := make([]rune, n)

    for i := range s {
        s[i] = letters[rand.Intn(len(letters))]
    }

    return string(s)
}

func main() {

    var size int
    var intArray []int64
    var floatArray []float64
    var stringArray []string

    flag.IntVar(&size, "size", 100, "The size of the array")
    flag.Parse()

    for i := 1; i <= size; i++ {
        intArray = append(intArray, rand.Int63n(1000))
    }

    fmt.Printf("Before Sorting : %v\n", intArray)
    fmt.Printf("After Sorting  : %v\n", quickSort(intArray))

    for i := 1; i <= size; i++ {
        floatArray = append(floatArray, float64(rand.Int63n(1000)) / 10)
    }

    fmt.Println("---")
    fmt.Printf("Before Sorting : %v\n", floatArray)
    fmt.Printf("After Sorting  : %v\n", quickSort(floatArray))


    for i := 1; i <= size; i++ {
        stringArray = append(stringArray, randomString(5))
    }

    fmt.Println("---")
    fmt.Printf("Before Sorting : %v\n", stringArray)
    fmt.Printf("After Sorting  : %v\n", quickSort(stringArray))

}

Testing #

Now we run go build and test the program

  • Show the usage
./quicksort --help
Usage of ./quicksort:
  -size int
        The size of the array (default 100)
  • Run the program with the default values
./quicksort
Before Sorting : [410 551 821 51 937 320 758 148 216 449 84 287 574 836 515 873 968 91 790 331 273 956 911 637 378 109 72 650 588 971 344 443 623 459 803 739 883 907 932 780 115 716 20 71 652 907 719 62 110 397 105 721 917 712 449 579 333 825 746 734 718 901 704 610 24 717 269 479 269 750 657 923 512 702 655 257 643 301 19 18 694 41 788 21 911 280 343 55 41 453 631 217 631 218 632 514 904 180 500 71]
After Sorting  : [18 19 20 21 24 41 41 51 55 62 71 71 72 84 91 105 109 110 115 148 180 216 217 218 257 269 269 273 280 287 301 320 331 333 343 344 378 397 410 443 449 449 453 459 479 500 512 514 515 551 574 579 588 610 623 631 631 632 637 643 650 652 655 657 694 702 704 712 716 717 718 719 721 734 739 746 750 758 780 788 790 803 821 825 836 873 883 901 904 907 907 911 911 917 923 932 937 956 968 971]
---
Before Sorting : [73.6 37.5 68.7 49.7 4.4 36.5 91.5 41 24.4 24.7 84 42.8 78.6 23.6 80.7 98.9 70 21.8 75.8 91.2 89.7 74.9 65.6 65 14 15 18.2 8 21.3 45 5.6 24 3.5 51.4 92.9 60.9 46.6 40 66.5 43.3 39.5 71.3 84 90.5 75.2 21.7 13.5 32 66.6 75.1 11.6 19 45.2 41.1 36.7 41.8 14.3 44.2 72.4 96.7 27.6 70.9 1 78.6 70 57.6 89.5 42.8 5.9 31.5 29.9 95.4 87.4 35.8 20.5 24 27 5.2 78.9 65.9 48 51.4 59.5 60.5 26.2 86.6 68.7 93.3 89 23.7 52.8 46.2 32.3 86.4 92.3 44.7 77.7 31.1 87.9 41.2]
After Sorting  : [1 3.5 4.4 5.2 5.6 5.9 8 11.6 13.5 14 14.3 15 18.2 19 20.5 21.3 21.7 21.8 23.6 23.7 24 24 24.4 24.7 26.2 27 27.6 29.9 31.1 31.5 32 32.3 35.8 36.5 36.7 37.5 39.5 40 41 41.1 41.2 41.8 42.8 42.8 43.3 44.2 44.7 45 45.2 46.2 46.6 48 49.7 51.4 51.4 52.8 57.6 59.5 60.5 60.9 65 65.6 65.9 66.5 66.6 68.7 68.7 70 70 70.9 71.3 72.4 73.6 74.9 75.1 75.2 75.8 77.7 78.6 78.6 78.9 80.7 84 84 86.4 86.6 87.4 87.9 89 89.5 89.7 90.5 91.2 91.5 92.3 92.9 93.3 95.4 96.7 98.9]
---
Before Sorting : [kjkZI vaBjM kXVbW Gvbqz gexyA LBsdj SGpng CwFkD ifIBu ufFMo WdiTs kZoQJ MqrTI CTojI YxyeS xZyfr oRODM bNDRZ nPNRW CJPMH DtJmH AYORs UfUMA psVgz HblmY YtEjV gwfFb bGGcn qbaER EunUZ jQXmZ OtaRL UtmYg mSVYB ADDvo xIfsf gPyCK mxIub eYTND tjAyR RDedM iyLpr ucjiO gjhYe VwBTC MLfrD GXqwp zwVGq MZcLV CxaSJ lDSYE ofkkE YeqkK HqgBp nbPbg HMLUI DjUMm pBHCS jMJjx zuaiI sNBak qSwQp OQgNc zgacz AInLq LIbAa tLYHd aopov FOkqI exsFz Xzrlc ztxcd JJFuy ZHRCo vgpVv lGsXa lGqAR mneBZ BFelh Xkzzf NaVtA yyqWz KqQFb ucqNJ YWRnc GKKLd TkNyo CSfkF ohsVV xSAZW EXejh AquXd aaaZl RHoNX vpayo Ssqcn CTuGZ amCTo ZvPyn aEphI]
After Sorting  : [ADDvo AInLq AYORs AquXd BFelh CJPMH CSfkF CTojI CTuGZ CwFkD CxaSJ DjUMm DtJmH EXejh EunUZ FOkqI GKKLd GXqwp Gvbqz HMLUI HblmY HqgBp JJFuy KqQFb LBsdj LIbAa MLfrD MZcLV MqrTI NaVtA OQgNc OtaRL RDedM RHoNX SGpng Ssqcn TkNyo UfUMA UtmYg VwBTC WdiTs Xkzzf Xzrlc YWRnc YeqkK YtEjV YxyeS ZHRCo ZvPyn aEphI aaaZl amCTo aopov bGGcn bNDRZ eYTND exsFz gPyCK gexyA gjhYe gwfFb ifIBu iyLpr jMJjx jQXmZ kXVbW kZoQJ kjkZI lDSYE lGqAR lGsXa mSVYB mneBZ mxIub nPNRW nbPbg oRODM ofkkE ohsVV pBHCS psVgz qSwQp qbaER sNBak tLYHd tjAyR ucjiO ucqNJ ufFMo vaBjM vgpVv vpayo xIfsf xSAZW xZyfr yyqWz zgacz ztxcd zuaiI zwVGq]
  • Run the program and test the size parameter
./quicksort --size=10
Before Sorting : [410 551 821 51 937 320 758 148 216 449]
After Sorting  : [51 148 216 320 410 449 551 758 821 937]
---
Before Sorting : [79 33.1 27.3 95.6 91.1 63.7 37.8 10.9 7.2 65]
After Sorting  : [7.2 10.9 27.3 33.1 37.8 63.7 65 79 91.1 95.6]
---
Before Sorting : [SjFbc XoEFf RsWxP LDnJO bCsNV lgTeM aPEZQ leQYh YzRyW JjPjz]
After Sorting  : [JjPjz LDnJO RsWxP SjFbc XoEFf YzRyW aPEZQ bCsNV leQYh lgTeM]
  • Run the program with an invalid value for the size
./quicksort -size -1.0
invalid value "-1.0" for flag -size: parse error
Usage of ./quicksort:
  -size int
        The size of the array (default 100)
  • Run the program with an invalid flag
./quicksort --sized 10
flag provided but not defined: -sized
Usage of ./quicksort:
  -size int
        The size of the array (default 100)