Is Quick Sort Algorithm Adaptive or not
Last Updated :
02 May, 2025
Adaptive sorting algorithms are designed to take advantage of existing order in the input data. This means, if the array is already sorted or partially sorted, an adaptive algorithm will recognize that and sort the array faster than it would for a completely random array.
Quick Sort is not an adaptive algorithm. Let us understand with an example.
arr[] = [1,2,3,4,5];
So in the above example, we can see that the array is sorted, but Quick Sort will sort the array by picking a corner element in every call to partition. In fact, a sorted input causes the worst case of QuickSort because every time the array is going to be partitioned with n-1 elements in one side.
Can we make QuickSort Adaptive?
The following are different ways to make QuickSort perform better for sorted or almost sorted inputs.
1) We can handle the above case by adding a check for sorted before proceeding to partitioning the array. Below is an example code for the same.
C++
#include <iostream>
#include <vector>
using namespace std;
int partition(vector<int>& arr, int low, int high) {
int pivot = arr[high];
// Index of smaller element and indicates
// the right position of pivot found so far
int i = low - 1;
// Traverse arr[low..high] and move all smaller
// elements on left side. Elements from low to
// i are smaller after every iteration
for (int j = low; j <= high - 1; j++) {
if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]);
}
}
// Move pivot after smaller elements and
// return its position
swap(arr[i + 1], arr[high]);
return i + 1;
}
bool isSorted(vector<int>&arr,int low, int high) {
for (int i = low; i < high - 1; i++) {
if (arr[i] > arr[i + 1]) {
return false;
}
}
return true;
}
void quickSort(vector<int>& arr, int low, int high) {
// If array is already Sorted then it will excecute
if(isSorted(arr,low,high))
{
return;
}
if (low < high) {
// pi is the partition return index of pivot
int pi = partition(arr, low, high);
// Recursion calls for smaller elements
// and greater or equals elements
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
int main() {
vector<int> arr = {1, 2, 3, 4, 5};
int n = arr.size();
quickSort(arr, 0, n - 1);
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
return 0;
}
Java
import java.util.Arrays;
public class GfG{
static int partition(int[] arr, int low, int high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j <= high - 1; j++) {
if (arr[j] < pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
static boolean isSorted(int[] arr, int low, int high) {
for (int i = low; i < high - 1; i++) {
if (arr[i] > arr[i + 1]) {
return false;
}
}
return true;
}
static void quickSort(int[] arr, int low, int high) {
if (isSorted(arr, low, high)) {
return;
}
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
int n = arr.length;
quickSort(arr, 0, n - 1);
System.out.println(Arrays.toString(arr));
}
}
Python
def partition(arr, low, high):
pivot = arr[high]
i = low - 1
for j in range(low, high):
if arr[j] < pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
def is_sorted(arr, low, high):
for i in range(low, high - 1):
if arr[i] > arr[i + 1]:
return False
return True
def quick_sort(arr, low, high):
if is_sorted(arr, low, high):
return
if low < high:
pi = partition(arr, low, high)
quick_sort(arr, low, pi - 1)
quick_sort(arr, pi + 1, high)
if __name__ == '__main__':
arr = [1, 2, 3, 4, 5]
n = len(arr)
quick_sort(arr, 0, n - 1)
print(arr)
C#
using System;
class GfG {
// Function to partition the array
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 arr[i] and arr[j]
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// Swap arr[i + 1] and arr[high] (pivot)
int temp2 = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp2;
return i + 1;
}
// QuickSort method to sort the array
static void QuickSortMethod(int[] arr, int low, int high) {
if (low < high) {
int pi = Partition(arr, low, high);
QuickSortMethod(arr, low, pi - 1);
QuickSortMethod(arr, pi + 1, high);
}
}
static void Main() {
int[] arr = { 1, 2, 3, 4, 5 };
int n = arr.Length;
QuickSortMethod(arr, 0, n - 1);
// Output the sorted array
Console.WriteLine(string.Join(" ", arr));
}
}
JavaScript
function partition(arr, low, high) {
let pivot = arr[high];
let i = low - 1;
for (let j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
[arr[i + 1], arr[high]] = [arr[high], arr[i + 1]];
return i + 1;
}
function isSorted(arr, low, high) {
for (let i = low; i < high - 1; i++) {
if (arr[i] > arr[i + 1]) {
return false;
}
}
return true;
}
function quickSort(arr, low, high) {
if (isSorted(arr, low, high)) {
return;
}
if (low < high) {
let pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
const arr = [1, 2, 3, 4, 5];
const n = arr.length;
quickSort(arr, 0, n - 1);
console.log(arr);
OutputArray before sorting : 1 2 3 4 5
Array after sorting : 1 2 3 4 5
If the array is already sorted, each element is traversed almost once. Therefore, the time complexity becomes O(n) and otherwise, it would have taken O(n2).
2) Instead of choosing a random or first element as pivot, pick the median of the first, middle, and last elements. This reduces the chance of worst-case behavior on nearly sorted arrays.
3) We can switch to Insertion Sort for smaller arrays. Insertion Sort is adaptive and performs very well on nearly sorted data. So many QuickSort implementations switch to Insertion Sort for small partitions (say, size < 10).
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem