Quick Sort Algorithm¶
Algorithm Introduction¶
Quick sort is an efficient sorting algorithm that uses a divide-and-conquer strategy. It selects a "pivot" element and partitions the array into two subarrays: elements less than the pivot and elements greater than the pivot, then recursively sorts the subarrays.
Algorithm Steps¶
- Select an element from the array as the "pivot"
- Reorder the array so that all elements with values less than the pivot come before it, while all elements with values greater than the pivot come after it
- Recursively apply the above steps to the subarrays of elements with smaller and larger values
Code Implementation¶
def quick_sort_inplace(arr, low, high):
if low < high:
# Partition operation, returns the final position of the pivot
pivot_pos = partition(arr, low, high)
# Recursively sort left and right subarrays
quick_sort_inplace(arr, low, pivot_pos - 1)
quick_sort_inplace(arr, pivot_pos + 1, high)
def partition(arr, low, high):
# Select last element as pivot
pivot = arr[high]
i = low - 1 # Boundary for elements less than pivot
for j in range(low, high):
if arr[j] <= pivot:
i += 1
# Swap arr[i] and arr[j]
arr[i], arr[j] = arr[j], arr[i]
# Place pivot in correct position
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
# Test
arr = [5, 3, 8, 4, 2]
quick_sort_inplace(arr, 0, len(arr) - 1)
print("Sorted array:", arr)
public class QuickSort {
public static void main(String[] args) {
int[] arr = {5, 3, 8, 4, 2};
quickSort(arr, 0, arr.length - 1);
System.out.println("Sorted array:");
for (int num : arr) {
System.out.print(num + " ");
}
}
public static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int pivot = partition(arr, low, high);
quickSort(arr, low, pivot - 1);
quickSort(arr, pivot + 1, high);
}
}
public static int partition(int[] arr, int low, int high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
// Swap elements
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// Place pivot in correct position
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
}
Complexity Analysis¶
- Time Complexity:
- Best case: O(n log n)
- Average case: O(n log n)
- Worst case: O(n²) (when array is already sorted or all elements are equal)
- Space Complexity: O(log n) (recursion call stack)
Sorting Example¶
Let's understand how quick sort works with a concrete example. Suppose we have an array: [5, 3, 8, 4, 2]
First Partition (Root Node)¶
- Select last element 2 as pivot
- Initialize pointer i = -1
- Traverse array, moving elements ≤ pivot to the left:
- Compare 5 with 2: 5 > 2, no swap
- Compare 3 with 2: 3 > 2, no swap
- Compare 8 with 2: 8 > 2, no swap
-
Compare 4 with 2: 4 > 2, no swap
-
Finally place pivot in correct position:
Now pivot 2 is in correct position (index 0), left side has no elements, right side has elements > 2.
Right Subarray Partition¶
Partition right subarray [5, 3, 8, 4]:
- Select 4 as pivot
- Partition process:
- Place pivot in correct position:
Now pivot 4 is in correct position (index 1), left side has elements < 4, right side has elements > 4.
Further Recursive Partitioning¶
- Partition
[3]: Single element, already sorted - Partition
[5, 8]: Result:[5, 8](already sorted)
Final Result¶
After all partitions, array becomes sorted: [2, 3, 4, 5, 8]
This example demonstrates key characteristics of quick sort: - Partitioning array into two parts using a pivot - Recursively sorting subarrays - Each partition places pivot in its final position - Compared to bubble sort, quick sort reduces comparisons through divide-and-conquer
Tree Visualization¶
Animation Demo¶
Exercises¶
- Implement quick sort with different pivot selection strategies (first element, middle element, random element)
- Analyze quick sort's performance on nearly sorted lists
- Compare quick sort's performance with merge sort and heap sort
- Implement quick sort with tail recursion optimization