In simple QuickSort algorithm, we select an element as pivot, partition the array around a pivot and recur for subarrays on the left and right of the pivot.
Consider an array which has many redundant elements. For example, {1, 4, 2, 4, 2, 4, 1, 2, 4, 1, 2, 2, 2, 2, 4, 1, 4, 4, 4}. If 4 is picked as a pivot in Simple Quick Sort, we fix only one 4 and recursively process remaining occurrences.
The idea of 3 way Quick Sort is to process all occurrences of the pivot and is based on Dutch National Flag algorithm.
In 3 Way QuickSort, an array arr[l..r] is divided in 3 parts:
a) arr[l..i] elements less than pivot.
b) arr[i+1..j-1] elements equal to pivot.
c) arr[j..r] elements greater than pivot.
Below is the implementation of the above algorithm.
C++
#include <bits/stdc++.h>
using namespace std;
void partition( int a[], int l, int r, int & i, int & j)
{
i = l - 1, j = r;
int p = l - 1, q = r;
int v = a[r];
while ( true ) {
while (a[++i] < v)
;
while (v < a[--j])
if (j == l)
break ;
if (i >= j)
break ;
swap(a[i], a[j]);
if (a[i] == v) {
p++;
swap(a[p], a[i]);
}
if (a[j] == v) {
q--;
swap(a[j], a[q]);
}
}
swap(a[i], a[r]);
j = i - 1;
for ( int k = l; k < p; k++, j--)
swap(a[k], a[j]);
i = i + 1;
for ( int k = r - 1; k > q; k--, i++)
swap(a[i], a[k]);
}
void quicksort( int a[], int l, int r)
{
if (r <= l)
return ;
int i, j;
partition(a, l, r, i, j);
quicksort(a, l, j);
quicksort(a, i, r);
}
void printarr( int a[], int n)
{
for ( int i = 0; i < n; ++i)
printf ( "%d " , a[i]);
printf ( "\n" );
}
int main()
{
int a[] = { 4, 9, 4, 4, 1, 9, 4, 4, 9, 4, 4, 1, 4 };
int size = sizeof (a) / sizeof ( int );
printarr(a, size);
quicksort(a, 0, size - 1);
printarr(a, size);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int i, j;
static void partition( int a[], int l, int r)
{
i = l - 1 ; j = r;
int p = l - 1 , q = r;
int v = a[r];
while ( true )
{
while (a[++i] < v)
;
while (v < a[--j])
if (j == l)
break ;
if (i >= j)
break ;
int temp = a[i];
a[i] = a[j];
a[j] = temp;
if (a[i] == v) {
p++;
temp = a[i];
a[i] = a[p];
a[p] = temp;
}
if (a[j] == v) {
q--;
temp = a[q];
a[q] = a[j];
a[j] = temp;
}
}
int temp = a[i];
a[i] = a[r];
a[r] = temp;
j = i - 1 ;
for ( int k = l; k < p; k++, j--)
{
temp = a[k];
a[k] = a[j];
a[j] = temp;
}
i = i + 1 ;
for ( int k = r - 1 ; k > q; k--, i++)
{
temp = a[i];
a[i] = a[k];
a[k] = temp;
}
}
static void quicksort( int a[], int l, int r)
{
if (r <= l)
return ;
i = 0 ; j = 0 ;
partition(a, l, r);
quicksort(a, l, j);
quicksort(a, i, r);
}
static void printarr( int a[], int n)
{
for ( int i = 0 ; i < n; ++i)
System.out.printf( "%d " , a[i]);
System.out.printf( "\n" );
}
public static void main(String[] args)
{
int a[] = { 4 , 9 , 4 , 4 , 1 , 9 , 4 , 4 , 9 , 4 , 4 , 1 , 4 };
int size = a.length;
printarr(a, size);
quicksort(a, 0 , size - 1 );
printarr(a, size);
}
}
|
Python3
def partition(arr, first, last, start, mid):
pivot = arr[last]
end = last
while (mid[ 0 ] < = end):
if (arr[mid[ 0 ]] < pivot):
arr[mid[ 0 ]], arr[start[ 0 ]] = arr[start[ 0 ]], arr[mid[ 0 ]]
mid[ 0 ] = mid[ 0 ] + 1
start[ 0 ] = start[ 0 ] + 1
elif (arr[mid[ 0 ]] > pivot):
arr[mid[ 0 ]], arr[end] = arr[end], arr[mid[ 0 ]]
end = end - 1
else :
mid[ 0 ] = mid[ 0 ] + 1
def quicksort(arr,first,last):
if (first > = last):
return
if (last = = first + 1 ):
if (arr[first] > arr[last]):
arr[first], arr[last] = arr[last], arr[first]
return
start = [first]
mid = [first]
partition(arr, first, last, start, mid)
quicksort(arr, first, start[ 0 ] - 1 )
quicksort(arr, mid[ 0 ], last)
arr = [ 4 , 9 , 4 , 4 , 1 , 9 , 4 , 4 , 9 , 4 , 4 , 1 , 4 ]
quicksort(arr, 0 , len (arr) - 1 )
print (arr)
|
C#
using System;
class GFG {
static void swap<T>( ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
public static void partition( int [] a, int l, int r,
ref int i, ref int j)
{
i = l - 1;
j = r;
int p = l - 1, q = r;
int v = a[r];
while ( true ) {
while (a[++i] < v)
;
while (v < a[--j])
if (j == l)
break ;
if (i >= j)
break ;
swap( ref a[i], ref a[j]);
if (a[i] == v) {
p++;
swap( ref a[p], ref a[i]);
}
if (a[j] == v) {
q--;
swap( ref a[j], ref a[q]);
}
}
swap( ref a[i], ref a[r]);
j = i - 1;
for ( int k = l; k < p; k++, j--)
swap( ref a[k], ref a[j]);
i = i + 1;
for ( int k = r - 1; k > q; k--, i++)
swap( ref a[i], ref a[k]);
}
public static void quicksort( int [] a, int l, int r)
{
if (r <= l)
return ;
int i = 0, j = 0;
partition(a, l, r, ref i, ref j);
quicksort(a, l, j);
quicksort(a, i, r);
}
public static void printarr( int [] a, int n)
{
for ( int i = 0; i < n; ++i)
Console.Write(a[i] + " " );
Console.Write( "\n" );
}
static void Main()
{
int [] a = { 4, 9, 4, 4, 1, 9, 4, 4, 9, 4, 4, 1, 4 };
int size = a.Length;
printarr(a, size);
quicksort(a, 0, size - 1);
printarr(a, size);
}
}
|
Javascript
<script>
var i, j;
function partition(a , l , r) {
i = l - 1;
j = r;
var p = l - 1, q = r;
var v = a[r];
while ( true ) {
while (a[++i] < v)
;
while (v < a[--j])
if (j == l)
break ;
if (i >= j)
break ;
var temp = a[i];
a[i] = a[j];
a[j] = temp;
if (a[i] == v) {
p++;
temp = a[i];
a[i] = a[p];
a[p] = temp;
}
if (a[j] == v) {
q--;
temp = a[q];
a[q] = a[j];
a[j] = temp;
}
}
var temp = a[i];
a[i] = a[r];
a[r] = temp;
j = i - 1;
for (k = l; k < p; k++, j--) {
temp = a[k];
a[k] = a[j];
a[j] = temp;
}
i = i + 1;
for (k = r - 1; k > q; k--, i++) {
temp = a[i];
a[i] = a[k];
a[k] = temp;
}
}
function quicksort(a , l , r) {
if (r <= l)
return ;
i = 0;
j = 0;
partition(a, l, r);
quicksort(a, l, j);
quicksort(a, i, r);
}
function printarr(a , n) {
for (i = 0; i < n; ++i)
document.write( " " + a[i]);
document.write( "<br/>" );
}
var a = [ 4, 9, 4, 4, 1, 9, 4, 4, 9, 4, 4, 1, 4 ];
var size = a.length;
printarr(a, size);
quicksort(a, 0, size - 1);
printarr(a, size);
</script>
|
Output
4 9 4 4 1 9 4 4 9 4 4 1 4
1 1 4 4 4 4 4 4 4 4 9 9 9
Time Complexity: O(N * log(N))
Where ‘N’ is the number of elements in the given array/list
The average number of recursive calls made to the quicksort function is log N, and every time the function is called we are traversing the given array/list which requires O(N) time. Thus, the total time complexity is O(N * log (N)).
Space Complexity: O(log N)
where ‘N’ is the number of elements in the given array/list.
Thanks to Utkarsh for suggesting above implementation.
Another Implementation using Dutch National Flag Algorithm
C++
#include <bits/stdc++.h>
using namespace std;
void swap( int * a, int * b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void printarr( int a[], int n)
{
for ( int i = 0; i < n; ++i)
printf ( "%d " , a[i]);
printf ( "\n" );
}
void partition( int a[], int low, int high, int & i, int & j)
{
if (high - low <= 1) {
if (a[high] < a[low])
swap(&a[high], &a[low]);
i = low;
j = high;
return ;
}
int mid = low;
int pivot = a[high];
while (mid <= high) {
if (a[mid] < pivot)
swap(&a[low++], &a[mid++]);
else if (a[mid] == pivot)
mid++;
else if (a[mid] > pivot)
swap(&a[mid], &a[high--]);
}
i = low - 1;
j = mid;
}
void quicksort( int a[], int low, int high)
{
if (low >= high)
return ;
int i, j;
partition(a, low, high, i, j);
quicksort(a, low, i);
quicksort(a, j, high);
}
int main()
{
int a[] = { 4, 9, 4, 4, 1, 9, 4, 4, 9, 4, 4, 1, 4 };
int size = sizeof (a) / sizeof ( int );
printarr(a, size);
quicksort(a, 0, size - 1);
printarr(a, size);
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 void printarr( int a[], int n)
{
for ( int i = 0 ; i < n; ++i)
System.out.printf( "%d " , a[i]);
System.out.printf( "\n" );
}
static void partition( int a[], int low, int high, int i, int j)
{
if (high - low <= 1 ) {
if (a[high] < a[low])
swap(a, high, low);
i = low;
j = high;
return ;
}
int mid = low;
int pivot = a[high];
while (mid <= high) {
if (a[mid] < pivot)
swap(a, low++, mid++);
else if (a[mid] == pivot)
mid++;
else if (a[mid] > pivot)
swap(a, mid, high--);
}
i = low - 1 ;
j = mid;
}
static void quicksort( int a[], int low, int high)
{
if (low >= high)
return ;
int i=low, j=high;
partition(a, low, high, i, j);
quicksort(a, low, i);
quicksort(a, j, high);
}
public static void main(String[] args)
{
int a[] = { 4 , 9 , 4 , 4 , 1 , 9 , 4 , 4 , 9 , 4 , 4 , 1 , 4 };
int size = a.length;
printarr(a, size);
quicksort(a, 0 , size - 1 );
printarr(a, size);
}
}
|
Python3
def swap(a,i,j) :
temp = a[i]
a[i] = a[j]
a[j] = temp
def printarr(a, n) :
for i in range (n) :
print (a[i],end = ' ' )
print ( "\n" )
def partition(a, low, high, i, j) :
if high - low < = 1 :
if a[high] < a[low] :
swap(a,high, low)
i = low
j = high
return
mid = low; pivot = a[high];
while mid < = high :
if a[mid] < pivot :
swap(a,low,mid)
low + = 1
mid + = 1
elif a[mid] = = pivot :
mid + = 1
elif a[mid] > pivot :
swap(a,mid,high)
high - = 1
i = low - 1
j = mid
def quickSort(a,low,high) :
if low > = high :
return
i = low; j = high;
partition(a,low,high,i,j)
quickSort(a,low,i)
quickSort(a,j,high)
if __name__ = = "__main__" :
a = [ 4 , 9 , 4 , 4 , 1 , 9 , 4 , 4 , 9 , 4 , 4 , 1 , 4 ]
size = len (a)
printarr(a,size)
quickSort(a, 0 ,size - 1 )
printarr(a,size)
|
C#
using System;
class GFG {
static void swap<T>( ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
public static void printarr( int [] a, int n)
{
for ( int i = 0; i < n; ++i)
Console.Write(a[i] + " " );
Console.Write( "\n" );
}
public static void partition( int [] a, int low, int high,
ref int i, ref int j)
{
if (high - low <= 1) {
if (a[high] < a[low])
swap( ref a[high], ref a[low]);
i = low;
j = high;
return ;
}
int mid = low;
int pivot = a[high];
while (mid <= high) {
if (a[mid] < pivot)
swap( ref a[low++], ref a[mid++]);
else if (a[mid] == pivot)
mid++;
else if (a[mid] > pivot)
swap( ref a[mid], ref a[high--]);
}
i = low - 1;
j = mid;
}
public static void quicksort( int [] a, int low, int high)
{
if (low >= high)
return ;
int i = 0, j = 0;
partition(a, low, high, ref i, ref j);
quicksort(a, low, i);
quicksort(a, j, high);
}
static void Main()
{
int [] a = { 4, 9, 4, 4, 1, 9, 4, 4, 9, 4, 4, 1, 4 };
int size = a.Length;
printarr(a, size);
quicksort(a, 0, size - 1);
printarr(a, size);
}
}
|
Javascript
<script>
function swap(arr, i, j) {
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
function printarr(a, n) {
for (let i = 0; i < n; ++i)
document.write(a[i]);
document.write( "<br>" );
}
function partition(a, low, high, i, j) {
if (high - low <= 1) {
if (a[high] < a[low])
swap(a, high, low);
i = low;
j = high;
return ;
}
let mid = low;
let pivot = a[high];
while (mid <= high) {
if (a[mid] < pivot)
swap(a, low++, mid++);
else if (a[mid] == pivot)
mid++;
else if (a[mid] > pivot)
swap(a, mid, high--);
}
i = low - 1;
j = mid;
}
function quicksort(a, low, high) {
if (low >= high)
return ;
let i = low, j = high;
partition(a, low, high, i, j);
quicksort(a, low, i);
quicksort(a, j, high);
}
let a = [4, 9, 4, 4, 1, 9, 4, 4, 9, 4, 4, 1, 4];
let size = a.length;
printarr(a, size);
quicksort(a, 0, size - 1);
printarr(a, size);
</script>
|
Output
4 9 4 4 1 9 4 4 9 4 4 1 4
1 1 4 4 4 4 4 4 4 4 9 9 9
Time Complexity: O(N2) The time complexity for this code is O(N*log(N)) in the average and best-case scenarios, and O(N^2) in the worst-case scenario.
Space Complexity: O(log N)
Thanks Aditya Goel for this implementation.
Reference:
http://algs4.cs.princeton.edu/lectures/23DemoPartitioning.pdf
http://www.sorting-algorithms.com/quick-sort-3-way
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
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 :
08 Mar, 2023
Like Article
Save Article