Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 45 additions & 22 deletions src/main/java/com/thealgorithms/sorts/QuickSort.java
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>The algorithm selects a pivot element and partitions the array into two
* subarrays such that:
* <ul>
* <li>Elements smaller than the pivot are placed on the left</li>
* <li>Elements greater than the pivot are placed on the right</li>
* </ul>
*
* <p>The subarrays are then recursively sorted until the entire array is ordered.
*
* <p>This implementation uses randomization to reduce the probability of
* encountering worst-case performance on already sorted inputs.
*
* <p>Time Complexity:
* <ul>
* <li>Best Case: O(n log n)</li>
* <li>Average Case: O(n log n)</li>
* <li>Worst Case: O(n^2)</li>
* </ul>
*
* <p>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 extends Comparable<T>> T[] sort(T[] array) {
doSort(array, 0, array.length - 1);
Expand All @@ -28,27 +40,33 @@ public <T extends Comparable<T>> 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 <T extends Comparable<T>> 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 <T extends Comparable<T>> 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);
Expand All @@ -58,21 +76,26 @@ private static <T extends Comparable<T>> 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 <T extends Comparable<T>> 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;
Expand Down