I.Description of quicksort
Divide: Partition (rearrange) the array A[p ‥ r] into two (possibly empty) subarrays A[p ‥ q - 1] and A[q + 1 ‥ r] such that each element of A[p ‥ q - 1] is less than or equal to A[q], which is, in turn, less than or equal to each element of A[q + 1 ‥ r]. Compute the index q as part of this partitioning procedure.
Conquer: Sort the two subarrays A[p ‥ q -1] and A[q +1 ‥ r] by recursive calls to quicksort.
Combine: Since the subarrays are sorted in place, no work is needed to combine them: the entire array A[p ‥ r] is now sorted.
The following procedure implements quicksort.
QUICKSORT(A, p, r)
1 if p < r
2 then q ← PARTITION(A, p, r)
3 QUICKSORT(A, p, q - 1)
4 QUICKSORT(A, q + 1, r)
To sort an entire array A, the initial call is QUICKSORT(A, 1, length[A]).
Partitioning the array
The key to the algorithm is the PARTITION procedure, which rearranges the subarray A[p ‥ r] in place.
PARTITION(A, p, r)
1 x ← A[r]
2 i ← p - 1
3 for j ← p to r - 1
4 do if A[j] ≤ x
5 then i ← i + 1
6 exchange A[i] ↔ A[j]
7 exchange A[i + 1] ↔ A[r]
8 return i + 1
code:
inline void ExchangeTwoElements(T& a, T& b)
{
T temp = 0;
temp = a;
a = b;
b = temp;
}
int ParitionUp(T A[], int p, int r)
{
int key = A[r];
int i = p-1;
int j=0;
for(j=p;j<r;j++)
{
if(A[j]<=key)
{
i=i+1;
ExchangeTwoElements(A[i],A[j]);
}
}
ExchangeTwoElements(A[i+1],A[r]);
// for(int k=p;k<=r;k++)
// {
// cout<<A[k]<<" ";
// }
// cout<<" key:"<<key<<endl;
return (i+1);
}
int ParitionDown(T A[], int p, int r)
{
int key = A[r];
int i = p-1;
int j=0;
for(j=p;j<r;j++)
{
if(A[j]>=key)
{
i=i+1;
ExchangeTwoElements(A[i],A[j]);
}
}
ExchangeTwoElements(A[i+1],A[r]);
// for(int k=p;k<=r;k++)
// {
// cout<<A[k]<<" ";
// }
// cout<<" key:"<<key<<endl;
return (i+1);
}
void QuickSortProxy(T A[],int p, int r)
{
if(p<r)
{
int q = 0;
q = ParitionUp(A,p,r);
//test array
QuickSortProxy(A,p,q-1);
QuickSortProxy(A,q+1,r);
}
else
{
return;
}
}
void QicckSort(T A[], int n)
{
QuickSortProxy(A,0,n-1);
}
notice:
1.the input is 0 and n-1, for pseudo-code, it form 1 to n.
2.the difference between ParitionUp and ParitionDown is just
if(A[j]<=key)
and
if(A[j]>=key)
.
Divided -and -Conquer:
The quickSort's key points is that Divided -and -Conquer.
1.A question is from item 1 to n , normally lick A(p,r);
2.devide it from two patch, normal lick p<<q<<r, A(p,q) and A(q,r)
3.At first,A(1,1) or A(1,2) ...which is knowing well to solve the problem
4.Thus using the recurrence,the problem will be solved at all.
II.A randomized version of quicksort
the key of Parition is a key-reason of Parition's time;
the worst case is the array is decreasing, the best is that it was increasing.
So, if we using a radom index number instead of A[r], the will be an average expend with time.
Add for :
RANDOMIZED-PARTITION(A, p, r)
1 i ← RANDOM(p, r)
2 exchange A[r] ↔ A[i]
3 return PARTITION(A, p, r)
The new quicksort calls RANDOMIZED-PARTITION in place of PARTITION:
RANDOMIZED-QUICKSORT(A, p, r)
1 if p < r
2 then q ← RANDOMIZED-PARTITION(A, p, r)
3 RANDOMIZED-QUICKSORT(A, p, q - 1)
4 RANDOMIZED-QUICKSORT(A, q + 1, r)