Open In App

Is Quick Sort Algorithm Adaptive or not

Last Updated : 02 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

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);

Output
Array 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).




Next Article
Article Tags :
Practice Tags :

Similar Reads