/* ========================================================
Sort: a[iLeft] a[iLeft+1] .... a[iRight-1]
======================================================== */
void QuickSort( double[] a, int iLeft, int iRight )
{
if ( iRight - iLeft ≤ 1 )
{
// An empty array or an array of 1 element don't need sorting !
return;
}
k = partition( a, iLeft, iRight );
// Returns the pos. of pivit after partitioning
QuickSort( a, iLeft, k ); // Sort left half of partitioned array
QucikSort( a, k+1, iRight); // Sort right half of partitioned array
}
|
|
|
Example:
![]() |
Observation:
|
|
Before sort: [2.5, 8.9, 1.1, 4.2, 9.2] Input: [2.5, 8.9, 1.1, 4.2, 9.2] a[] = [2.5, 8.9, 1.1, 4.2, 9.2] Pivot = 9.2 After partition: [4.2, 2.5, 8.9, 1.1, 9.2] Input: [4.2, 2.5, 8.9, 1.1] a[] = [4.2, 2.5, 8.9, 1.1, 9.2] Pivot = 1.1 After partition: [1.1, 4.2, 2.5, 8.9, 9.2] Input: [] a[] = [1.1, 4.2, 2.5, 8.9, 9.2] Done. Input: [4.2, 2.5, 8.9] a[] = [1.1, 4.2, 2.5, 8.9, 9.2] Pivot = 8.9 After partition: [1.1, 2.5, 4.2, 8.9, 9.2] Input: [2.5, 4.2] a[] = [1.1, 2.5, 4.2, 8.9, 9.2] Pivot = 4.2 After partition: [1.1, 2.5, 4.2, 8.9, 9.2] Input: [2.5] a[] = [1.1, 2.5, 4.2, 8.9, 9.2] Done. |
I have highlighted the pivots in each partition() call.
/* ========================================================
Sort: a[iLeft] a[iLeft+1] .... a[iRight-1]
======================================================== */
void QuickSort( double[] a, int iLeft, int iRight )
{
if ( iRight - iLeft ≤ 1 )
{
// An empty array or an array of 1 element don't need sorting !
return;
}
k = partition( a, iLeft, iRight );
// Worst case: ONE array has (n-1) elements
// the OTHER array has 0 elements
QuickSort( a, iLeft, k ); // Sort left half of partitioned array
QucikSort( a, k+1, iRight); // Sort right half of partitioned array
}
|
Summary of the execution:
QuickSort( input array with n elements ) { .... partition( a (array with n elements) ); QuickSort( array with (n-1) elements ); QuickSort( array with 0 elements ); } |
Amount of work done by QuickSort( array of size n ) = Amount of work done by partition ( array of n elements ) + Amount of work done by QuickSort( array of size n-1 ) + 0 |
|
T(n) = partition(n) + T(n-1) // partition(n) = n = n + T(n-1) = T(n-1) + n T(1) = 1 // For the if-check operation |
Solving the recurrence relation:
T(n) = T(n-1) + n // T(n-1) = T(n-2) + (n-1) = T(n-2) + (n-1) + n = T(n-3) + (n-2) + (n-1) + n = ... = T(1) + 2 + 3 + ... + (n-1) + n // T(1) = 1 = 1 + 2 + 3 + ... + (n-1) + n n (n+1) = --------- 2 |
n (n+1) T(n) = --------- = O(n2) 2 |
(So Quick Sort is really "slow sort" in the worst case !!!)
|
![]() |
/* ========================================================
Sort: a[iLeft] a[iLeft+1] .... a[iRight-1]
======================================================== */
void QuickSort( double[] a, int iLeft, int iRight )
{
if ( iRight - iLeft ≤ 1 )
{
// An empty array or an array of 1 element don't need sorting !
return;
}
k = partition( a, iLeft, iRight );
// Best case: TWO array with n/2 elements
QuickSort( a, iLeft, k ); // Sort left half of partitioned array
QucikSort( a, k+1, iRight); // Sort right half of partitioned array
}
|
Summary of the execution:
QuickSort( input array with n elements ) { .... partition( a (array with n elements) ); QuickSort( array with n/2 elements ); QuickSort( array with n/2 elements ); } |
Amount of work done by QuickSort( array of size n ) = Amount of work done by partition( array of n elements ) + Amount of work done by QuickSort( array of size n/2 ) + Amount of work done by QuickSort( array of size n/2 ) |
|
T(n) = partition(n) + 2*T(n/2) // partition(n) = n = n + 2*T(n/2) = 2*T(n/2) + n T(1) = 1 // For the if-check operation |
Solving the recurrence relation:
T(n) = 2*T(n/2) + n // T(n/2) = 2*T(n/4) + (n/2) = 2*[ 2*T(n/4) + n/2 ] + n = 22*T(n/4) + n + n = 22*T(n/4) + 2n // T(n/4) = 2*T(n/8) + (n/4) = 22*[ 2*T(n/8) + (n/4) ] + 2n = 23*T(n/8) + 22*(n/4) + 2n = 23*T(n/8) + n + 2n = 23*T(n/8) + 3n = 24*T(n/16) + 4n and so on.... = 2k*T(n/(2k)) + k*n // Keep going until: n/(2k) = 1 <==> n = 2k = 2k*T(1) + k*n = 2k*1 + k*n = 2k + k*n // n = 2k = n + k*n = n + (lg(n))*n = n*( lg(n) + 1 ) ~= n*lg(n)) |
T(n) = n*log(n) |
(So Quick Sort is indeed fast in the fast case !!!)
I have a hand-written derivation here: click here
T(n) ~= 2(n+1) Hn+1 (Hn = n-th Harmonic number) = O( n*log(n) ) |
How to run the program:
|