QuickSort using Random Pivoting

In this article we will discuss how to implement QuickSort using random pivoting. In QuickSort we first partition the array in place such that all elements to the left of the pivot element are smaller, while all elements to the right of the pivot are greater that the pivot. Then we recursively call the same procedure for left and right subarrays.

Unlike merge sort we don’t need to merge the two sorted arrays. Thus Quicksort requires lesser auxillary space than Merge Sort, which is why it is often preferred to Merge Sort.Using a randomly generated pivot we can further improve the time complexity of QuickSort.

We have discussed at two popular methods for partioning the arrays-Hoare’s vs Lomuto partition scheme
It is advised that the reader has read that article or knows how to implement the QuickSort using either of the two partition schemes.



Algorithm for random pivoting using Lomuto Partitioning


partition(arr[], lo, hi) 
    pivot = arr[hi]
    i = lo     // place for swapping
    for j := lo to hi – 1 do
        if arr[j] <= pivot then
            swap arr[i] with arr[j]
            i = i + 1
    swap arr[i] with arr[hi]
    return i

partition_r(arr[], lo, hi)
    r = Random Number from lo to hi
    Swap arr[r] and arr[hi]
    return partition(arr, lo, hi)

quicksort(arr[], lo, hi)
    if lo < hi
        p = partition_r(arr, lo, hi)
        quicksort(arr, p-1, hi)
        quicksort(arr, p+1, hi)
 

Algorithm for random pivoting using Hoare Partitioning

partition(arr[], lo, hi)
   pivot = arr[lo]
   i = lo - 1  // Initialize left index
   j = hi + 1  // Initialize right index

   // Find a value in left side greater
   // than pivot
   do
      i = i + 1
   while arr[i]  pivot

   if i >= j then 
      return j

   swap arr[i] with arr[j]
   
partition_r(arr[], lo, hi)
    r = Random number from lo to hi
    Swap arr[r] and arr[lo]
    return partition(arr, lo, hi)

quicksort(arr[], lo, hi)
    if lo < hi
        p = partition_r(arr, lo, hi)
        quicksort(arr, p, hi)
        quicksort(arr, p+1, hi)
        

Lomuto (C++)

filter_none

edit
close

play_arrow

link
brightness_4
code

/* C++ implementation QuickSort using Lomuto's partition
   Scheme.*/
#include <cstdlib>
#include <iostream>
using namespace std;
  
/* This function takes last element as pivot, places
  the pivot element at its correct position in sorted
  array, and places all smaller (smaller than pivot)
  to left of pivot and all greater elements to right
  of pivot */
int partition(int arr[], int low, int high)
{
    int pivot = arr[high]; // pivot
    int i = (low - 1); // Index of smaller element
  
    for (int j = low; j <= high - 1; j++) {
  
        // If current element is smaller than or
        // equal to pivot
        if (arr[j] <= pivot) {
  
            i++; // increment index of smaller element
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[high]);
    return (i + 1);
}
  
// Generates Random Pivot, swaps pivot with
// end element and calls the partition function
int partition_r(int arr[], int low, int high)
{
    // Generate a random number in between
    // low .. high
    srand(time(NULL));
    int random = low + rand() % (high - low);
  
    // Swap A[random] with A[high]
    swap(arr[random], arr[high]);
  
    return partition(arr, low, high);
}
  
/* The main function that implements QuickSort
arr[] --> Array to be sorted,
low --> Starting index,
high --> Ending index */
void quickSort(int arr[], int low, int high)
{
    if (low < high) {
  
        /* pi is partitioning index, arr[p] is now
        at right place */
        int pi = partition_r(arr, low, high);
  
        // Separately sort elements before
        // partition and after partition
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}
  
/* Function to print an array */
void printArray(int arr[], int size)
{
    int i;
    for (i = 0; i < size; i++)
        printf("%d ", arr[i]);
    printf("\n");
}
  
// Driver program to test above functions
int main()
{
    int arr[] = { 10, 7, 8, 9, 1, 5 };
    int n = sizeof(arr) / sizeof(arr[0]);
    quickSort(arr, 0, n - 1);
    printf("Sorted array: \n");
    printArray(arr, n);
    return 0;
}

chevron_right


Hoare (C++)

filter_none

edit
close

play_arrow

link
brightness_4
code

/* C++ implementation of QuickSort using Hoare's
   partition scheme. */
#include <cstdlib>
#include <iostream>
using namespace std;
  
/* This function takes last element as pivot, places
   the pivot element at its correct position in sorted
    array, and places all smaller (smaller than pivot)
   to left of pivot and all greater elements to right
   of pivot */
int partition(int arr[], int low, int high)
{
    int pivot = arr[low];
    int i = low - 1, j = high + 1;
  
    while (true) {
  
        // Find leftmost element greater than
        // or equal to pivot
        do {
            i++;
        } while (arr[i] < pivot);
  
        // Find rightmost element smaller than
        // or equal to pivot
        do {
            j--;
        } while (arr[j] > pivot);
  
        // If two pointers met.
        if (i >= j)
            return j;
  
        swap(arr[i], arr[j]);
    }
}
  
// Generates Random Pivot, swaps pivot with
// end element and calls the partition function
// In Hoare partition the low element is selected
// as first pivot
int partition_r(int arr[], int low, int high)
{
    // Generate a random number in between
    // low .. high
    srand(time(NULL));
    int random = low + rand() % (high - low);
  
    // Swap A[random] with A[high]
    swap(arr[random], arr[low]);
  
    return partition(arr, low, high);
}
  
/* The main function that implements QuickSort
 arr[] --> Array to be sorted,
  low  --> Starting index,
  high  --> Ending index */
void quickSort(int arr[], int low, int high)
{
    if (low < high) {
        /* pi is partitioning index, arr[p] is now
           at right place */
        int pi = partition_r(arr, low, high);
  
        // Separately sort elements before
        // partition and after partition
        quickSort(arr, low, pi);
        quickSort(arr, pi + 1, high);
    }
}
  
/* Function to print an array */
void printArray(int arr[], int n)
{
    for (int i = 0; i < n; i++)
        printf("%d ", arr[i]);
    printf("\n");
}
  
// Driver program to test above functions
int main()
{
    int arr[] = { 10, 7, 8, 9, 1, 5 };
    int n = sizeof(arr) / sizeof(arr[0]);
    quickSort(arr, 0, n - 1);
    printf("Sorted array: \n");
    printArray(arr, n);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to illustrate Randomised Quick Sort 
import java.util.*;
  
class RandomisedQuickSort 
    public static int N = 5;
    public static int[] arr = new int[N];
      
    // This Function helps in calculating random 
    // numbers between low(inclusive) and high(inclusive)
    void random(int low,int high)
    {
      
        Random rand= new Random();
        int pivot = rand.nextInt(high-low) + low;
          
        int temp1=arr[pivot];
        arr[pivot]=arr[high];
        arr[high]=temp1;
    }
      
    /* This function takes last element as pivot, 
    places the pivot element at its correct 
    position in sorted array, and places all 
    smaller (smaller than pivot) to left of 
    pivot and all greater elements to right 
    of pivot */
      
    int partition(int arr[], int low, int high) 
    
        // pivot is choosen randomly
        int pivot = arr[high]; 
      
  
        int i = (low-1); // index of smaller element 
        for (int j = low; j < high; j++) 
        
            // If current element is smaller than or 
            // equal to pivot 
            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] (or pivot) 
        int temp = arr[i+1]; 
        arr[i+1] = arr[high]; 
        arr[high] = temp; 
  
        return i+1
    
  
  
    /* The main function that implements QuickSort() 
    arr[] --> Array to be sorted, 
    low --> Starting index, 
    high --> Ending index */
    void sort(int arr[], int low, int high) 
    
        if (low < high) 
        
            /* pi is partitioning index, arr[pi] is 
            now at right place */
            int pi = partition(arr, low, high); 
  
            // Recursively sort elements before 
            // partition and after partition 
            sort(arr, low, pi-1); 
            sort(arr, pi+1, high); 
        
    
  
    /* A utility function to print array of size n */
    static void printArray(int arr[]) 
    
        int n = arr.length; 
        for (int i = 0; i < n; ++i) 
            System.out.print(arr[i]+" "); 
        System.out.println(); 
    
  
    // Driver code 
    public static void main(String args[]) 
    
        int arr[] = {10, 7, 8, 9, 1, 5}; 
        int n = arr.length; 
  
        RandomisedQuickSort ob = new RandomisedQuickSort(); 
        ob.sort(arr, 0, n-1); 
  
        System.out.println("sorted array"); 
        printArray(arr); 
    
  
// This code is contributed by Ritika Gupta.

chevron_right


Lomuto(Python)

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python implementation QuickSort using 
# Lomuto's partition Scheme.
import random
  
'''
The function which implements QuickSort.
arr :- array to be sorted.
start :- starting index of the array.
stop :- ending index of the array.
'''
def quicksort(arr, start , stop):
    if(start < stop):
          
        # pivotindex is the index where 
        # the pivot lies in the array
        pivotindex = partitionrand(arr, start, stop)
          
        # At this stage the array is partially sorted 
        # around the pivot. Seperately sorting the 
        # left half of the array and the right half of the array.
        quicksort(arr , start , pivotindex - 1)
        quicksort(arr, pivotindex + 1, stop)
  
# This function generates random pivot, swaps the first
# element with the pivot and calls the partition fucntion.
def partitionrand(arr , start, stop):
  
    # Generating a random number between the 
    # starting index of the array and the
    # ending index of the array.
    randpivot = random.randrange(start, stop)
  
    # Swapping the starting element of the array and the pivot
    arr[start], arr[randpivot] = arr[randpivot], arr[start]
    return partition(arr, start, stop)
  
'''
This function takes the first element as pivot, 
places the pivot element at the correct position 
in the sorted array. All the elements are re-arranged 
according to the pivot, the elements smaller than the
pivot is places on the left and the elements
greater than the pivot is placed to the right of pivot.
'''
def partition(arr,start,stop):
    pivot = start # pivot
    i = start + 1 # a variable to memorize where the 
                  # partition in the array starts from.
    for j in range(start + 1, stop + 1):
          
        # if the current element is smaller or equal to pivot,
        # shift it to the left side of the partition.
        if arr[j] <= arr[pivot]:
            arr[i] , arr[j] = arr[j] , arr[i]
            i = i + 1
    arr[pivot] , arr[i - 1] = arr[i - 1] , arr[pivot]
    pivot = i - 1
    return (pivot)
  
# Driver Code
if __name__ == "__main__":
    array = [10, 7, 8, 9, 1, 5]
    quicksort(array, 0, len(array) - 1)
    print(array)
  
# This code is contributed by soumyasaurav

chevron_right


Haore(Python)

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python implementation QuickSort using 
# Hoare's partition Scheme.
  
import random
  
'''
The function which implements randomised QuickSort,
using Haore's partition scheme.
arr :- array to be sorted.
start :- starting index of the array.
stop :- ending index of the array.
'''
def quicksort(arr, start, stop):
    if(start < stop):
          
        # pivotindex is the index where
        # the pivot lies in the array
        pivotindex = partitionrand(arr, start, stop)
          
        # At this stage the array is partially sorted 
        # around the pivot. seperately sorting the 
        # left half of the array and the right half of the array.
        quicksort(arr , start , pivotindex)
        quicksort(arr, pivotindex + 1, stop)
  
# This function generates random pivot, swaps the first
# element with the pivot and calls the partition fucntion.
def partitionrand(arr , start, stop):
  
    # Generating a random number between 
    # the starting index of the array and 
    # the ending index of the array.
    randpivot = random.randrange(start, stop)
  
    # Swapping the starting element of 
    # the array and the pivot
    arr[start], arr[randpivot] = arr[randpivot], arr[start]
    return partition(arr, start, stop)
  
'''
This function takes the first element as pivot, 
places the pivot element at the correct position 
in the sorted array. All the elements are re-arranged 
according to the pivot, the elements smaller than 
the pivot is places on the left and the elements
greater than the pivot is placed to the right of pivot.
'''
def partition(arr,start,stop):
    pivot = start # pivot
    i = start - 1
    j = stop + 1
    while True:
        while True:
            i = i + 1
            if arr[i] >= arr[pivot]:
                break
        while True:
            j = j - 1
            if arr[j] <= arr[pivot]:
                break
        if i >= j:
            return j
        arr[i] , arr[j] = arr[j] , arr[i]
  
# Driver Code
if __name__ == "__main__":
    array = [10, 7, 8, 9, 1, 5]
    quicksort(array, 0, len(array) - 1)
    print(array)
  
# This code is contributed by soumyasaurav

chevron_right



Output:

Sorted array: 1 5 7 8 9 10

Analysis of Randomized Quick Sort

Notes

  • Using random pivoting we improve the expected or average time complexity to O (N log N). The Worst Case complexity is still O ( N^2 ).


My Personal Notes arrow_drop_up

Intern at GeeksForGeeks

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : RitikaGupta4, soumyasaurav



Article Tags :
Practice Tags :


5


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.