Quick Sort, as the name suggests, is a sorting algorithm known for its efficiency. It is one of the best-performing sorting algorithms, with a significant caveat: it should only be used when the worst-case scenario is unlikely to occur. Understanding its mechanics and performance profile is crucial for effective implementation.
Quick Sort follows the divide and conquer pattern, similar to Merge Sort. The algorithm works by selecting a 'pivot' value from the array and partitioning the input array into sub-arrays based on if the values are less than or greater than the pivot. The sub-arrays are then sorted recursively.
The choice of pivot is critical. Ideally, the pivot should be the median of the array, but since the array is unsorted, this is not feasible. Common strategies include selecting the middle value we'll see later on why.
For clarity's sake let's start with the swap function:
const swap = (arr, idx1, idx2) => {
[arr[idx1], arr[idx2]] = [arr[idx2], arr[idx1]];
};
Then our pivot helper:
function pivot(arr, start = 0, end = arr.length - 1) {
let pivot = arr[start];
let swapIdx = start;
for (let i = start + 1; i <= end; i++) {
if (pivot > arr[i]) {
swapIdx++;
swap(arr, swapIdx, i);
}
}
swap(arr, start, swapIdx);
return swapIdx;
}
Now that we have our pivot helper we need a way to execute it recursively until everything is sorted because after one iteration only what is less than our pivot will end up to the left of it and what is greater to the right of it, in other words only our pivot is at the correct spot. To illustrate this with an example, consider an array 2, 4, 1:
Here with a small dataset one pivot execution is enough but if we were to have a larger one we would need to recursively do it until our array is fully sorted.
Let's find out how:
function quickSort(arr, start_index = 0, end_index = arr.length - 1) {
if (start_index >= end_index) return arr;
let pivot_index = pivot(arr, start_index, end_index);
// Left
quickSort(arr, start_index, pivot_index - 1);
// Right
quickSort(arr, pivot_index + 1, end_index);
return arr;
}
const arr = [2, 4, 1, 3, 5, 1]
pivot(arr); // Just 1 pivot => [1, 1, 2, 3, 5, 4]
quickSort(arr); // Here 2 pivots => [1, 1, 2, 3, 4, 5]
For optimal performance, it is advisable to select the middle value as the pivot. This approach increases the likelihood of avoiding the smallest and largest values in practical use cases. To implement this, modify your pivot function as follows:
function pivot(arr, start = 0, end = arr.length - 1) {
const pivot = arr[Math.floor((end + start) / 2)];
let i = start;
let j = end;
while (i <= j) {
while (arr[i] < pivot) {
i++;
}
while (arr[j] > pivot) {
j--;
}
if (i <= j) {
swap(arr, i, j);
i++;
j--;
}
}
return i;
}
Quick Sort is highly efficient but has a significant caveat in its worst-case scenario:
Quick Sort is suitable for most sorting tasks, especially when the worst-case scenario is unlikely. However, other algorithms like Merge Sort may be more consistent and stable in certain scenarios.
Quick Sort is a powerful and efficient sorting algorithm with an average time complexity of O(n log n). However, it is essential to be aware of its worst-case scenario, which can degrade performance to O(n^2). By carefully selecting the pivot and understanding the algorithm's mechanics, you can leverage Quick Sort effectively in your projects.
Happy coding!
Honestly i am no one, i've just been coding for 3 years now and i like to document every solutions to every problem i encounter. Extracting as much code snippets and tutorials i can so that if i ever need it again i just have to pop back here and get a quick refresher.
Feel free to me through this learning journey by providing any feedback and if you wanna support me: