演算法代碼如下:
/// <summary>
/// 快速排序的分隔,即:對於一個指定的主元x,找到位置i,使得i的左邊元素都小於等於x,右邊都大於等於x.
/// </summary>
/// <param name="A"></param>
/// <param name="p"></param>
/// <param name="q"></param>
/// <returns></returns>
private int QuickSortPartion(int[] A, int p, int q)
{
int theCount = q - p + 1;
//只有一個元素的情況,返回-1表示不用繼續分割
if (theCount==1)
{
return -1;
}
//如果元素為2,則不用繼續分割,只需要簡單處理即可,這可以節省一些時間,但不是必須.
if (theCount == 2)
{
if (A[p] > A[q])
{
int tmp = A[p];
A[p] = A[q];
A[q] = tmp;
}
return -1;
}
//隨機擷取主元
Random theR=new Random(10);
int theMasterIndex = theR.Next(1, theCount);
int theMasterP = p + theMasterIndex -1;
//找到主元x,並與下界元素交換。
int theX = A[theMasterP];
A[theMasterP] = A[p];
A[p] = theX;
//尋找i,使得小於i位置的元素都小於等於thex,大於i位置的元素都大於thex.i初始位置為p.
int i = p;
//j初始位置為i+1;
for(int j=p+1;j<=q;j++)
{
//如果A[j]小於等於主元,則主元位置i右移一位,A[i]與A[j]交換
if (A[j] <= theX)
{
i++;
int theTmp = A[j];
A[j] = A[i];
A[i] = theTmp;
}
}
//做一次交換,將主元放到位置i.
A[p] = A[i];
A[i] = theX;
return i;
}
/// <summary>
/// 快速排序,主函數.
/// </summary>
/// <param name="A"></param>
/// <param name="S"></param>
/// <param name="E"></param>
private void QuickSort(int[] A, int S, int E)
{
//先找劃分位置i
int theDivI = QuickSortPartion(A, S, E);
//不需要劃分
if (theDivI < 0)
{
return;
}
int theP1_S = S, theP1_E = theDivI - 1;
int theP2_S = theDivI + 1, theP2_E = E;
//對左邊遞迴快排
if (theP1_E >= S)
{
QuickSort(A, theP1_S, theP1_E);
}
//對右邊遞迴快排.
if (theP2_S <= theP2_E)
{
QuickSort(A, theP2_S, theP2_E);
}
}
分治策略三步曲是:分,治,合。快排和歸併排序同樣採用的是分治策略,而且分治後的策略分支樹都為2,但快排的優勢在於,它不需要“合”,而歸併排序的兩個分支策略完成後,還有一個歸併的過程。所以時間複雜度上歸併顯然不如快排。快排可以達到時間複雜度θ(n*lg(n)),歸併的是θ(n*lg(n)).但快排的實際時間複雜度與其實現和輸入都有關,最壞的情況,快排的時間複雜度也會達到θ(n^2),這個方面,歸併排序的時間複雜度要均衡一些,與輸入序列相關性不大。