[排序演算法]--快速排序的Java實現
阿新 • • 發佈:2019-01-01
快速排序
所謂快速排序:基於分治的思想,是氣泡排序的改進型。首先在陣列中選擇一個基準點並把基準點放於序列的開頭(該基準點的選取可能影響快速排序的效率,關於基準點的選擇方法後面再講解),然後分別從陣列的兩端掃描陣列,設兩個指示標誌(lo指向起始位置,hi指向末尾),首先從後半部分開始,如果發現有元素比該基準點的值小,就交換lo和hi位置的值,然後從前半部分開始掃秒,發現有元素大於基準點的值,就交換lo和hi位置的值,如此往復迴圈,直到lo>=hi,然後把基準點的值放到hi這個位置,一次排序就完成了。之後再採用遞迴的方式分別對前半部分和後半部分排序,當前半部分和後半部分均有序時該陣列自然也就有序了。
在網上找的關於一次快速排序的示意圖如下圖:
演算法的實現:
1) 首先是進行一輪快速排序的函式:
/**
* 一次快速排序
* @param array 陣列
* @param lo 陣列的前下標
* @param hi 陣列的後下標
* @return key的下標index,也就是分片的間隔點
*/
public static int partition(int []array,int lo,int hi){
/** 固定的切分方式 */
int key=array[lo];//選取了基準點
while(lo<hi){
//從後半部分向前掃描
while(array[hi]>=key&&hi>lo){
hi--;
}
array[lo]=array[hi];
//從前半部分向後掃描
while(array[lo]<=key&&hi>lo){
lo++;
}
array[hi]=array[lo];
}
array[hi]=key;//最後把基準存入
return hi;
}
2) 快速排序的函式如下:
/**
* 快速排序
* @param array
* @param lo
* @param hi
*/
public static void quickSort(int[] array,int lo ,int hi){
if(lo>=hi){
return ;
}
//進行第一輪排序獲取分割點
int index=partition(array,lo,hi);
//排序前半部分
quickSort(array, lo, index - 1);
//排序後半部分
quickSort(array,index+1,hi);
}
3) 測試函式:
public static void main(String[] args) {
int[] arr = {1,9,3,12,7,8,3,4,65,22};
quickSort(arr, 0, arr.length-1);
for(int i:arr){
System.out.print(i+",");
}
}
輸出是:
1,3,3,4,7,8,9,12,22,65,
快速排序基準點的優化
對於基準點的優化一般有三種:固定切分,隨機切分和三數取樣切分。固定切分的效率並不是太好,隨機切分是常用的一種切分,效率比較高,最壞情況下時間複雜度有可能為O(N^2)。對於三數取中選擇基準點是最理想的一種。
下面給出三個數取中間數的演算法實現:
//三數取中
//下面的兩步保證了array[hi]是最大的;
int mid=lo+(hi-lo)/2;
if(array[mid]>array[hi]){
swap(array[mid],array[hi]);
}
if(array[lo]>array[hi]){
swap(array[lo],array[hi]);
}
//接下來只用比較array[lo]和array[mid],讓較小的在array[lo]位置就OK。
if(array[mid]>array[lo]){
swap(array[mid],array[lo]);
}
int key=array[lo];
上面的swap(a, b); 函式的含義就是交換a和b的值。