André Albano @onablaerdna
I'm a Geophysicist and Coder. I work with seismic inversion algorithms,
software development, well log analysis and so on.
Published on: May 31, 2024 at 12:00 PM
An in-depth look at the efficient QuickSort algorithm and its inner workings.
Written by: Andre Albano
Sorting algorithms are a fundamental aspect of computer science, used in various applications ranging from data organization to optimizing search algorithms. One of the most efficient sorting algorithms is QuickSort. In this post, we will explore the QuickSort algorithm in detail, understand how it works, and comparing it to Merge Sort (the focus of my last post about sorting algorithms).
QuickSort is a divide-and-conquer algorithm that works by selecting a ‘pivot’ element from the array and partitioning the other elements into two sub-arrays, according to whether they are less than or greater than the pivot. The sub-arrays are then sorted recursively.
Here’s a step-by-step explanation of the QuickSort algorithm:
Here is the pseudocode for the QuickSort algorithm:
function QuickSort(A, low, high)
if low < high
pivotIndex <- Partition(A, low, high)
QuickSort(A, low, pivotIndex - 1)
QuickSort(A, pivotIndex + 1, high)
return A
function Partition(A, low, high)
pivot <- A[high]
i <- low - 1
for j <- low to high - 1
if A[j] < pivot
i <- i + 1
swap A[i] with A[j]
swap A[i + 1] with A[high]
return i + 1
In the pseudocode above, A
is the array to be sorted, low
is the starting index,
and high
is the ending index of the array. To call the function, you normally use:
QuickSort(A, 0, A.length - 1)
The time complexity of QuickSort depends on the pivot selection and partitioning process:
The space complexity of QuickSort is due to the stack space used by recursion.
The video below showcases the merge sort algorithm in a random array of 50 elements.
Unlike QuickSort, MergeSort has a guaranteed time complexity of but requires additional space for merging, making its space complexity .
def quicksort(A, lo, hi):
"""Implements the Lomuto partition
scheme for Quick Sort algorithm"""
if lo >= hi or lo < 0:
return "Undefined"
p = partition(A, lo, hi)
quicksort(A, lo, p - 1) # Left side of pivot
quicksort(A, p + 1, hi) # Right side of pivot
return A
def partition(A, lo, hi):
"""Partition the array"""
pivot = A[hi] # Choose the last element as the pivot
i = lo
for j in range(lo, hi):
if A[j] <= pivot:
A[i], A[j] = A[j], A[i]
i = i + 1
A[i], A[hi] = A[hi], A[i]
return i # the pivot index
ARRAY = [2, 5, 6, 4, 8, 3, 1, 9, 7]
print(quicksort(ARRAY, 0, len(ARRAY) - 1))
fn quicksort<T: Ord>(arr: &mut [T]) {
if arr.len() <= 1 {
return;
}
let pivot = partition(arr);
quicksort(&mut arr[..pivot]);
quicksort(&mut arr[pivot + 1..]);
}
fn partition<T: Ord>(arr: &mut [T]) -> usize {
let pivot_index = arr.len() - 1;
let mut i = 0;
for j in 0..pivot_index {
if arr[j] <= arr[pivot_index] {
arr.swap(i, j);
i += 1;
}
}
arr.swap(i, pivot_index);
i
}
fn main() {
let mut arr = [5, 2, 9, 1, 7, 6, 3, 8, 4];
quicksort(&mut arr);
println!("{:?}", arr);
}
QuickSort is a highly efficient and commonly used sorting algorithm, particularly suitable for large datasets due to its average-case time complexity of . While its performance can degrade to in the worst case, with good pivot selection strategies, it remains one of the fastest sorting algorithms available.
André Albano @onablaerdna
I'm a Geophysicist and Coder. I work with seismic inversion algorithms,
software development, well log analysis and so on.