單向掃描法的思路:
第一步首先定主元,一般設置爲數組起始位置。
然後定義兩個指針,一個是掃描指針sp,指向主元的下一個元素
一個指右側指針bigger,指向數組最後一個元素
然後sp指針開始向右掃描,如果掃描到的元素小於主元的話sp指針向後移動sp++,否則的話 此時sp指向的元素和bigger指向的元素進行交換,然後bigger向前移動bigger--。直到sp大於bigger的時候,循環結束。
最後返回主元的正確位置,這個位置就是bigger,就是主元的左側元素都比它小,右側元素都比它的位置。
public static void quickSort(int[] A,int p, int r)
{
if(p<r)
{
int q = partition(A,p,r);
quickSort(A,p,q-1);
quickSort(A,q+1,r);
}
}
//返回主元最終的位置
public static int partition(int[] A,int p, int r)
{
int pivot = A[p]; //一般設置p位置的元素爲主元
int sp = p+1; //掃描指針 左側指針
int bigger = r; //右側指針
while(sp<=bigger)
{
if(A[sp] <=pivot)
{
sp++;
}else
{
swap(A,sp,bigger); //交換sp和bigger位置的元素
bigger--;
}
}
swap(A,p,bigger);
return bigger;
}
雙向掃描思路:
第一步首先定主元,一般設置爲數組起始位置。
然後定義兩個指針,一個是左指針left,指向主元的下一個元素
一個右指針right,指向數組最後一個元素
從left開始向後掃描,找到第一個比主元的大的元素,然後right開始向前掃描,找到第一個比主元小的元素,此時交換left和right位置的元素。直到兩個指針交叉之後,結束循環。
循環結束之後,right指向的位置就是最後一個小於等於主元的位置,也就是主元應該待的位置,那麼就進行交換right和p位置的元素。此時就一輪快排結束,主元左側的元素都小於主元,主元右側的元素都大於主元。
//返回主元最終的位置
public static int partition2(int[] A,int p, int r)
{
//優化 在p r mid之間,選擇一箇中間值做爲主元
int midIndex = p+(r-p)/2; //中間下標
int midValueIndex = -1; //中值的下標
if(A[p] <=A[midIndex] &&A[p]>=A[r])
{
midValueIndex = p;
}else if(A[r]<=A[midIndex] && A[r]>=A[p])
{
midValueIndex = r;
}else
{
midValueIndex = midIndex;
}
swap(A,p,midValueIndex);
int pivot = A[p]; //一般設置p位置的元素爲主元
int left = p+1; // 左側指針
int right = r; //右側指針
while(left<=right)
{
while(left<=right && A[left] <= pivot){
left++;
}
while(left<=right && A[right] >pivot)
{
right--;
}
if(left < right)
{
swap(A, left, right);
}
}
swap(A, p, right);
return right;
}
public static void swap(int[] A,int p, int r)
{
int swap = A[p];
A[p] = A[r];
A[r] = swap;
}