backQuicksort in notes
2022-03-02
Quicksort is an efficient, easy-to-implement in-place sorting algorithm. The average case for quicksort is O(n log n). Although merge sort is a better candidate when we take the worst-case complexity of Quicksort into account. However, quicksort has a smaller constant than mergesort, making it a better candidate for some cases.
The algorithm is as follows:
If we translate the above steps to code.
package quicksort
func Quicksort(arr []int) []int {
return quicksort(arr, 0, len(arr)-1)
}
func quicksort(arr []int, l, h int) []int {
if l < h {
k := partition(arr, 0, h)
quicksort(arr, 0, k-1)
quicksort(arr, k+1, h)
}
return arr
}
Clearly partition function is doing the magic.
The most common implementations of partition are Lomuto partition scheme and Hoare partitio scheme.
func partition(arr []int, lb, ub int) int {
pivot := arr[lb] // Choose the first element of array as pivot
// start and end are pointers beginning at the lower and upper bounds of the array
start, end := lb, ub
for {
// stop iterations if pointer cross each other.
if start > end {
break
}
// keep moving the start pointers towards right
// until an element bigger than pivot is found.
for arr[start] <= pivot {
start++
}
// move end pointer towards left of the array
// until element smaller than pivot is found.
for arr[end] > pivot {
end--
}
// swap the element of the array pointed by start and end.
arr[start], arr[end] = arr[end], arr[start]
}
// swap the pivot to start pointer position.
arr[lb], arr[start] = arr[start], arr[lb]
return start
}
This is a simpler implementation of the partitioning function.
func partition(arr []int, lb, ub int) int {
pivot := arr[ub]
i := lb
for j := lb; j < ub; j++ {
if arr[j] <= pivot {
arr[i], arr[j] = arr[j], arr[i]
i++
}
}
arr[i], arr[ub] = arr[ub], arr[i]
return i
}
TODO: This is actually not sorting elements properly.