1. 程式人生 > >[排序演算法]--快速排序的Java實現

[排序演算法]--快速排序的Java實現

快速排序

所謂快速排序:基於分治的思想,是氣泡排序的改進型。首先在陣列中選擇一個基準點並把基準點放於序列的開頭(該基準點的選取可能影響快速排序的效率,關於基準點的選擇方法後面再講解),然後分別從陣列的兩端掃描陣列,設兩個指示標誌(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的值。