先把數列的最後一個數挑選出來,作爲一種中間值,然後分別從數列的兩端向中間靠近,從左向右遍歷時,遇到比中間值大的數則把這個數的索引leftPtr先下來,然後再從右往左遍歷,遇到比中間值小的數,就把這個數的索引rightPtr也記錄下來,最後讓leftPtr和rightPtr出的數交換,然後再分別從兩端接着遍歷,按照這個交換規則,最終可以讓所以比中間值小的數放到數列的左邊,所有比中間值大的數都放在右邊,然後再把這個中間值(也就是數列的最後一個數)與中間位置上的數(索引爲 數組長度/2 的數)交換這樣這一層排序算是完成。當然快速排序也稱爲分段排序,所以,在這一層排序完之後,會把左右兩端的數從中間分開看作是兩個子數列,然後再分別對兩個子數列按照如上規則進行排序,然後兩個子數列要再分成更短的兩個數列,就這樣不停的分下去最後知道它們不可分位置。最終從整體到局部形成一個順序的數列。
/**
* 快速分段排序 準備階段
* @param arr
* @param left 表示這個子數列在這個數列的開始位置索引
* @param right 表示這個子數列在這個數列的結束位置索引
* @param point 中間數索引
* @return
*/
public static int partition(int[] arr,int left,int right,int point){
int leftPtr=left-1;
int rightPtr=right;
while(true){
/**
* 數組先從左向右遍歷,如果left>right則停止遍歷,如果在左邊
* 遇到比關鍵數大的數,就停止,並記錄當前遍歷的到數leftPtr,然後
* 進行從右往左遍歷,如果left>right則停止遍歷,如果在右邊遇到比
* 關鍵數小的數就停止,並記錄當前遍歷到額數rightPtr,這時兩個遍
* 歷都完成後,將leftPtr與rightPtr處的數進行交換,這樣就可以
* 不斷將較大的數放在關鍵數右邊,將較小的數放在關鍵數左邊。
*/
while(leftPtr<rightPtr&&arr[++leftPtr]<point);
while(leftPtr<rightPtr&&arr[--rightPtr]>point);
if(leftPtr>=rightPtr){
break;
}else{
int temp;
temp=arr[leftPtr];//交換數據
arr[leftPtr]=arr[rightPtr];
arr[rightPtr]=temp;
}
}
/**
*一次分段排序後,關鍵數左與左右兩邊的數順序已經排好,這時,就可以把在
*最右邊的數(關鍵數),放在中間,與左右形成正確的順序,然後把中間那個
*數換到最右邊,進行下一次分段排序。
*/
int temp=arr[leftPtr];
arr[leftPtr]=arr[right];
arr[right]=temp;
return leftPtr;
}
/**
* 快速排序法(分段)
* @param arr
* @param left
* @param right
*/
public static void sort(int[] arr,int left,int right){
if(left>right){
return;
}
int point=arr[right];//始終把最右端的的數挑出來當作中間數
int partition=partition(arr,left,right,point);//返回交換後的中間數索引
sort(arr,left, partition-1);//對左端進行排序
sort(arr,partition+1, right);//對右端進行排序
}
public static void main(String[] args) {
int[] m={2,11,2,5,7,0,3,-1,8,4,6,12};
sort(m,0,m.length-1);
for(int i=0;i<m.length;i++){
System.out.print(m[i]+" ");
}
}