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 than 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 auxiliary 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 partitioning 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, lo , p-1)
quicksort(arr, p+1, hi)
Implementation using Lomuto Partitioning:
C++
#include <cstdlib>
#include <time.h>
#include <iostream>
using namespace std;
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++;
swap(arr[i], arr[j]);
}
}
swap(arr[i + 1], arr[high]);
return (i + 1);
}
int partition_r( int arr[], int low, int high)
{
srand ( time (NULL));
int random = low + rand () % (high - low);
swap(arr[random], arr[high]);
return partition(arr, low, high);
}
void quickSort( int arr[], int low, int high)
{
if (low < high) {
int pi = partition_r(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
void printArray( int arr[], int size)
{
int i;
for (i = 0; i < size; i++)
cout<<arr[i]<< " " ;
}
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;
}
|
C
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int partition( int arr[], int low, int high)
{
int pivot = arr[low];
int i = low - 1, j = high + 1;
while (1) {
do {
i++;
} while (arr[i] < pivot);
do {
j--;
} while (arr[j] > pivot);
if (i >= j)
return j;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int partition_r( int arr[], int low, int high)
{
srand ( time (0));
int random = low + rand () % (high - low);
int temp = arr[random];
arr[random] = arr[low];
arr[low] = temp;
return partition(arr, low, high);
}
void quickSort( int arr[], int low, int high)
{
if (low < high) {
int pi = partition_r(arr, low, high);
quickSort(arr, low, pi);
quickSort(arr, pi + 1, high);
}
}
void printArray( int arr[], int n)
{
for ( int i = 0; i < n; i++)
printf ( "%d " , arr[i]);
printf ( "\n" );
}
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;
}
|
Java
import java.util.*;
class RandomizedQsort
{
static void random( int arr[], 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;
}
static int partition( int arr[], int low, int high)
{
random(arr,low,high);
int pivot = arr[high];
int i = (low- 1 );
for ( int j = low; j < high; 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 void sort( int arr[], int low, int high)
{
if (low < high)
{
int pi = partition(arr, low, high);
sort(arr, low, pi- 1 );
sort(arr, pi+ 1 , high);
}
}
static void printArray( int arr[])
{
int n = arr.length;
for ( int i = 0 ; i < n; ++i)
System.out.print(arr[i]+ " " );
System.out.println();
}
public static void main(String args[])
{
int arr[] = { 10 , 7 , 8 , 9 , 1 , 5 };
int n = arr.length;
sort(arr, 0 , n- 1 );
System.out.println( "Sorted array" );
printArray(arr);
}
}
|
Python3
import random
def quicksort(arr, start , stop):
if (start < stop):
pivotindex = partitionrand(arr,\
start, stop)
quicksort(arr , start , pivotindex - 1 )
quicksort(arr, pivotindex + 1 , stop)
def partitionrand(arr , start, stop):
randpivot = random.randrange(start, stop)
arr[start], arr[randpivot] = \
arr[randpivot], arr[start]
return partition(arr, start, stop)
def partition(arr,start,stop):
pivot = start
i = start + 1
for j in range (start + 1 , stop + 1 ):
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)
if __name__ = = "__main__" :
array = [ 10 , 7 , 8 , 9 , 1 , 5 ]
quicksort(array, 0 , len (array) - 1 )
print (array)
|
C#
using System;
class RandomizedQsort
{
static int partition( int [] arr, int low, int high)
{
random(arr, low, high);
int pivot = arr[high];
int i = (low-1);
for ( int j = low; j < high; j++)
{
if (arr[j] < pivot)
{
i++;
int tempp = arr[i];
arr[i] = arr[j];
arr[j] = tempp;
}
}
int tempp2 = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = tempp2;
return i + 1;
}
static int random( int [] arr, int low, int high)
{
Random rand = new Random();
int pivot = rand.Next() % (high - low) + low;
int tempp1 = arr[pivot];
arr[pivot] = arr[high];
arr[high] = tempp1;
return partition(arr, low, high);
}
static void sort( int [] arr, int low, int high)
{
if (low < high)
{
int pi = partition(arr, low, high);
sort(arr, low, pi - 1);
sort(arr, pi + 1, high);
}
}
static void printArray( int [] arr)
{
int n = arr.Length;
for ( int i = 0; i < n; ++i)
Console.Write(arr[i] + " " );
Console.WriteLine();
}
static public void Main ()
{
int [] arr = {10, 7, 8, 9, 1, 5};
int n = arr.Length;
sort(arr, 0, n-1);
Console.WriteLine( "sorted array" );
printArray(arr);
}
}
|
Javascript
function quicksort(arr, start, stop) {
if (start < stop) {
let pivotindex = partitionrand(arr, start, stop);
quicksort(arr, start, pivotindex - 1);
quicksort(arr, pivotindex + 1, stop);
}
}
function partitionrand(arr, start, stop) {
let randpivot = Math.floor(Math.random() * (stop - start + 1)) + start;
[arr[start], arr[randpivot]] = [arr[randpivot], arr[start]];
return partition(arr, start, stop);
}
function partition(arr, start, stop) {
let pivot = start;
let i = start + 1;
for (let j = start + 1; j <= stop; j++) {
if (arr[j] <= arr[pivot]) {
[arr[i], arr[j]] = [arr[j], arr[i]];
i++;
}
}
[arr[pivot], arr[i - 1]] = [arr[i - 1], arr[pivot]];
pivot = i - 1;
return pivot;
}
let array = [10, 7, 8, 9, 1, 5];
quicksort(array, 0, array.length - 1);
console.log(array);
|
Output
Sorted array:
1 5 7 8 9 10
Time Complexity: O(N*N)
Auxiliary Space: O(N) // due to recursive call stack
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
while(True)
// Find a value in left side greater than pivot
do
i = i + 1
while arr[i] < pivot
// Find a value in right side smaller than pivot
do
j = j - 1
while arr[j] > pivot
if i >= j then
return j
else
swap arr[i] with arr[j]
end while
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, lo, p)
quicksort(arr, p+1, hi)
Implementation using Hoare’s Partitioning:
C++
#include <cstdlib>
#include <iostream>
using namespace std;
int partition( int arr[], int low, int high)
{
int pivot = arr[low];
int i = low - 1, j = high + 1;
while ( true ) {
do {
i++;
} while (arr[i] < pivot);
do {
j--;
} while (arr[j] > pivot);
if (i >= j)
return j;
swap(arr[i], arr[j]);
}
}
int partition_r( int arr[], int low, int high)
{
srand ( time (NULL));
int random = low + rand () % (high - low);
swap(arr[random], arr[low]);
return partition(arr, low, high);
}
void quickSort( int arr[], int low, int high)
{
if (low < high) {
int pi = partition_r(arr, low, high);
quickSort(arr, low, pi);
quickSort(arr, pi + 1, high);
}
}
void printArray( int arr[], int n)
{
for ( int i = 0; i < n; i++)
printf ( "%d " , arr[i]);
printf ( "\n" );
}
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;
}
|
Java
import java.util.*;
class GFG
{
static void swap( int [] arr, int i, int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static int partition( int [] arr, int low, int high)
{
int rIndex = (low) + ( int )(Math.random() * (high - low + 1 ));
swap(arr, low, rIndex);
int pivot = arr[low];
int i = low - 1 , j = high + 1 ;
while ( true ) {
do {
i++;
} while (arr[i] < pivot);
do {
j--;
} while (arr[j] > pivot);
if (i >= j)
return j;
swap(arr, i, j);
}
}
static void quickSort( int [] arr, int low, int high)
{
if (low < high) {
int p = partition(arr, low, high);
quickSort(arr, low, p);
quickSort(arr, p + 1 , high);
}
}
public static void main(String[] args)
{
int [] arr = { 10 , 7 , 8 , 9 , 1 , 5 };
quickSort(arr, 0 , arr.length - 1 );
System.out.println( "Sorted array : " );
System.out.print(Arrays.toString(arr));
}
}
|
Python3
import random
def quicksort(arr, start, stop):
if (start < stop):
pivotindex = partitionrand(arr,\
start, stop)
quicksort(arr , start , pivotindex)
quicksort(arr, pivotindex + 1 , stop)
def partitionrand(arr , start, stop):
randpivot = random.randrange(start, stop)
arr[start], arr[randpivot] = \
arr[randpivot], arr[start]
return partition(arr, start, stop)
def partition(arr,start,stop):
pivot = start
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]
if __name__ = = "__main__" :
array = [ 10 , 7 , 8 , 9 , 1 , 5 ]
quicksort(array, 0 , len (array) - 1 )
print (array)
|
C#
using System;
public class GFG {
public static void Main()
{
int [] arr = { 10, 7, 8, 9, 1, 5 };
int n = arr.Length;
quickSort(arr, 0, n - 1);
Console.WriteLine( "Sorted array: " );
printArray(arr, n);
}
public static int partition( int [] arr, int low,
int high)
{
int pivot = arr[low];
int i = low - 1, j = high + 1;
while ( true ) {
do {
i++;
} while (arr[i] < pivot);
do {
j--;
} while (arr[j] > pivot);
if (i >= j)
return j;
swap(arr, i, j);
}
}
public static int partition_r( int [] arr, int low,
int high)
{
Random rnd = new Random();
int random = low + rnd.Next(high - low);
swap(arr, random, low);
return partition(arr, low, high);
}
public static void quickSort( int [] arr, int low,
int high)
{
if (low < high) {
int pi = partition_r(arr, low, high);
quickSort(arr, low, pi);
quickSort(arr, pi + 1, high);
}
}
public static void printArray( int [] arr, int n)
{
for ( int i = 0; i < n; i++)
Console.Write( "{0} " , arr[i]);
Console.Write( "\n" );
}
public static void swap( int [] arr, int i, int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
|
Javascript
function partition(arr, low, high)
{
let pivot = arr[low];
let i = low - 1, j = high + 1;
while ( true ) {
do {
i++;
} while (arr[i] < pivot);
do {
j--;
} while (arr[j] > pivot);
if (i >= j)
return j;
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
function partition_r(arr, low, high)
{
let random = low + Math.random() * (high - low);
let temp = arr[random];
arr[random] = arr[low];
arr[low] = arr[random];
return partition(arr, low, high);
}
function quickSort(arr, low, high)
{
if (low < high) {
let pi = partition_r(arr, low, high);
quickSort(arr, low, pi);
quickSort(arr, pi + 1, high);
}
}
function printArray(arr, n)
{
for (let i = 0; i < n; i++)
process.stdout.write(arr[i] + " " );
}
let arr = [ 10, 7, 8, 9, 1, 5 ];
let n = arr.length
quickSort(arr, 0, n - 1);
console.log( "Sorted array: " );
printArray(arr, n);
|
Output
Sorted array:
1 5 7 8 9 10
Time Complexity: O(N*N)
Auxiliary Space: O(N) // due to recursive call stack
Implementation using generateRandomPivot function :
Here is an implementation without using Hoare’s and Lomuto partition scheme
Implementation of QuickSort using random pivoting without partitioning:
C++
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void swap( int * a, int * b) {
int temp = *a;
*a = *b;
*b = temp;
}
int generateRandomPivot( int low, int high) {
srand ( time (NULL));
return low + rand () % (high - low + 1);
}
void quickSort( int arr[], int low, int high) {
if (low < high) {
int pivotIndex = generateRandomPivot(low, high);
int pivotValue = arr[pivotIndex];
swap(&arr[pivotIndex], &arr[high]);
int i = low - 1;
for ( int j = low; j < high; j++) {
if (arr[j] < pivotValue) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i+1], &arr[high]);
quickSort(arr, low, i);
quickSort(arr, i+2, high);
}
}
int main() {
int arr[] = {5, 2, 7, 3, 1, 6, 4, 8};
int n = sizeof (arr)/ sizeof (arr[0]);
cout << "Original array: " ;
for ( int i = 0; i < n; i++) {
cout << arr[i] << " " ;
}
quickSort(arr, 0, n-1);
cout << "\nSorted array: " ;
for ( int i = 0; i < n; i++) {
cout << arr[i] << " " ;
}
return 0;
}
|
Java
import java.util.Random;
public class QuickSort {
static void swap( int [] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static int generateRandomPivot( int low, int high) {
Random random = new Random();
return random.nextInt(high - low + 1 ) + low;
}
static void quickSort( int [] arr, int low, int high) {
if (low < high) {
int pivotIndex = generateRandomPivot(low, high);
int pivotValue = arr[pivotIndex];
swap(arr, pivotIndex, high);
int i = low - 1 ;
for ( int j = low; j < high; j++) {
if (arr[j] < pivotValue) {
i++;
swap(arr, i, j);
}
}
swap(arr, i + 1 , high);
quickSort(arr, low, i);
quickSort(arr, i + 2 , high);
}
}
public static void main(String[] args) {
int [] arr = { 5 , 2 , 7 , 3 , 1 , 6 , 4 , 8 };
int n = arr.length;
System.out.print( "Original array: " );
for ( int num : arr) {
System.out.print(num + " " );
}
System.out.println();
quickSort(arr, 0 , n - 1 );
System.out.print( "Sorted array: " );
for ( int num : arr) {
System.out.print(num + " " );
}
System.out.println();
}
}
|
Python3
import random
def swap(arr, i, j):
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
def generateRandomPivot(low, high):
return random.randint(low, high)
def quickSort(arr, low, high):
if low < high:
pivotIndex = generateRandomPivot(low, high)
pivotValue = arr[pivotIndex]
swap(arr, pivotIndex, high)
i = low - 1
for j in range (low, high):
if arr[j] < pivotValue:
i + = 1
swap(arr, i, j)
swap(arr, i + 1 , high)
quickSort(arr, low, i)
quickSort(arr, i + 2 , high)
arr = [ 5 , 2 , 7 , 3 , 1 , 6 , 4 , 8 ]
n = len (arr)
print ( "Original array:" , arr)
quickSort(arr, 0 , n - 1 )
print ( "Sorted array:" , arr)
|
C#
using System;
class Program {
static void Swap( int [] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static int GenerateRandomPivot( int low, int high) {
Random random = new Random();
return low + random.Next(high - low + 1);
}
static void QuickSort( int [] arr, int low, int high) {
if (low < high) {
int pivotIndex = GenerateRandomPivot(low, high);
int pivotValue = arr[pivotIndex];
Swap(arr, pivotIndex, high);
int i = low - 1;
for ( int j = low; j < high; j++) {
if (arr[j] < pivotValue) {
i++;
Swap(arr, i, j);
}
}
Swap(arr, i+1, high);
QuickSort(arr, low, i);
QuickSort(arr, i+2, high);
}
}
static void Main() {
int [] arr = {5, 2, 7, 3, 1, 6, 4, 8};
int n = arr.Length;
Console.Write( "Original array: " );
for ( int i = 0; i < n; i++) {
Console.Write(arr[i] + " " );
}
QuickSort(arr, 0, n-1);
Console.Write( "\nSorted array: " );
for ( int i = 0; i < n; i++) {
Console.Write(arr[i] + " " );
}
}
}
|
Javascript
function swap(arr, i, j) {
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
function generateRandomPivot(low, high) {
return Math.floor(Math.random() * (high - low + 1)) + low;
}
function quickSort(arr, low, high) {
if (low < high) {
let pivotIndex = generateRandomPivot(low, high);
let pivotValue = arr[pivotIndex];
swap(arr, pivotIndex, high);
let i = low - 1;
for (let j = low; j < high; j++) {
if (arr[j] < pivotValue) {
i++;
swap(arr, i, j);
}
}
swap(arr, i + 1, high);
quickSort(arr, low, i);
quickSort(arr, i + 2, high);
}
}
let arr = [5, 2, 7, 3, 1, 6, 4, 8];
let n = arr.length;
console.log( "Original array: [" + arr.join( ", " ) + "]" );
quickSort(arr, 0, n - 1);
console.log( "Sorted array: [" + arr.join( ", " ) + "]" );
|
Output
Original array: 5 2 7 3 1 6 4 8
Sorted array: 1 2 3 4 5 6 7 8
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 ).
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
14 Sep, 2023
Like Article
Save Article