diff --git a/src/main/java/com/thealgorithms/sorts/QuickSort.java b/src/main/java/com/thealgorithms/sorts/QuickSort.java index a025e6909259..b0ca8b9f159d 100644 --- a/src/main/java/com/thealgorithms/sorts/QuickSort.java +++ b/src/main/java/com/thealgorithms/sorts/QuickSort.java @@ -1,24 +1,36 @@ package com.thealgorithms.sorts; /** - * @author Varun Upadhyay (https://github.com/varunu28) - * @author Podshivalov Nikita (https://github.com/nikitap492) + * QuickSort is a divide-and-conquer sorting algorithm. + * + *

The algorithm selects a pivot element and partitions the array into two + * subarrays such that: + *

+ * + *

The subarrays are then recursively sorted until the entire array is ordered. + * + *

This implementation uses randomization to reduce the probability of + * encountering worst-case performance on already sorted inputs. + * + *

Time Complexity: + *

+ * + *

Space Complexity: O(log n) due to recursion stack (in-place sorting). + * + * @author Varun Upadhyay + * @author Podshivalov Nikita * @see SortAlgorithm */ + class QuickSort implements SortAlgorithm { - /** - * Generic Quick Sort algorithm. - * - * Time Complexity: - * - Best case: O(n log n) – pivot splits array roughly in half each time. - * - Average case: O(n log n) - * - Worst case: O(n^2) – occurs when pivot consistently produces unbalanced splits. - * - * Space Complexity: O(log n) – recursion stack, in-place sorting. - * - * @see SortAlgorithm - */ @Override public > T[] sort(T[] array) { doSort(array, 0, array.length - 1); @@ -28,27 +40,33 @@ public > T[] sort(T[] array) { /** * The sorting process * - * @param left The first index of an array - * @param right The last index of an array * @param array The array to be sorted + * @param left The first index of an array + * @param right The last index of an array */ private static > void doSort(T[] array, final int left, final int right) { + // Continue sorting only if the subarray has more than one element if (left < right) { + // Randomly choose a pivot and partition the array final int pivot = randomPartition(array, left, right); + // Recursively sort elements before the pivot doSort(array, left, pivot - 1); + // Recursively sort elements after the pivot doSort(array, pivot, right); } } /** - * Randomize the array to avoid the basically ordered sequences + * Randomizes the array to avoid already ordered or nearly ordered sequences * * @param array The array to be sorted - * @param left The first index of an array + * @param left The first index of an array * @param right The last index of an array * @return the partition index of the array */ private static > int randomPartition(T[] array, final int left, final int right) { + // Randomizing the pivot helps avoid worst-case performance + // for already sorted or nearly sorted arrays final int randomIndex = left + (int) (Math.random() * (right - left + 1)); SortUtils.swap(array, randomIndex, right); return partition(array, left, right); @@ -58,21 +76,26 @@ private static > int randomPartition(T[] array, final in * This method finds the partition index for an array * * @param array The array to be sorted - * @param left The first index of an array - * @param right The last index of an array Finds the partition index of an - * array + * @param left The first index of an array + * @param right The last index of an array */ private static > int partition(T[] array, int left, int right) { final int mid = (left + right) >>> 1; + // Choose the middle element as the pivot final T pivot = array[mid]; - + // Move the left and right pointers towards each other while (left <= right) { + // Move left pointer until an element >= pivot is found while (SortUtils.less(array[left], pivot)) { ++left; } + + // Move right pointer until an element <= pivot is found while (SortUtils.less(pivot, array[right])) { --right; } + + // Swap elements that are on the wrong side of the pivot if (left <= right) { SortUtils.swap(array, left, right); ++left;