1. 程式人生 > >資料結構與演算法——排序演算法之快速排序

資料結構與演算法——排序演算法之快速排序

資料結構與演算法——排序演算法之快速排序

  • 快速排序定義

    快速排序由C. A. R. Hoare在1962年提出通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。

  • 快速排序的優勢

    桶排序浪費空間嚴重,而氣泡排序解決了這一問題,但是在演算法的執行效率上大打折扣。快速排序既解決了空間浪費問題,又使運算速度大幅提高,可謂一舉雙得。

  • 自然語言描述(以降序為例)

    • Step1: 選定一個最左或最右為基準數(本例選擇最左)
    • Step2: 定義兩個標誌變數,分別指向資料的兩邊有(以下簡稱左標和右標)。
    • Step3: 右標開始向左移動,直到遇到小於基準數的數時停下來。
    • Step4: 左標開始向右移動,直到遇到大於基準數的數時停下來。
    • Step5: 將左右兩標所指數字互換,重複第三四五步,直到左右兩標指向同一數字,這三個步驟稱為一趟。
    • Step6 : 兩標指向的同一數字與基準數互換完成快排。

- 程式碼實現:

  [ 一 ]  C語言實現
#include <stdio.h>
int a[101],n;//定義全域性變數,這兩個變數需要在子函式中使用
void quicksort(int left, int right); int main() { int i,j; //讀入資料 scanf("%d",&n); for(i=1; i<=n; i++) scanf("%d",&a[i]); quicksort(1,n);//快速排序呼叫 //輸出排序後的結果 for(i=1; i<=n; i++) printf("%d ",a[i]); return 0; } void quicksort(int left, int right) { int i,j,t,temp; if(left >
right) return; temp = a[left];//temp中存的就是基準數 i = left; j = right; while(i != j) { //順序很重要要先從右往左找 while(a[j] >= temp && i<j) j--; //再從左往右找 while(a[i] <= temp && i<j) i++; //交換兩個數在陣列中的位置 if(i<j) //當哨兵i和哨兵j沒有相遇時 { t = a[i]; a[i] = a[j]; a[j] =t; } } //最終將基準數歸位 a[left] = a[i]; a[i] = temp; quicksort(left,i-1);//繼續處理左邊的,這裡是一個遞迴的過程 quicksort(i+1,right);//繼續處理右邊的,這裡是一個遞迴的過程 }
  • [ 二 ] java實現

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;
    }
    
    public static void sort(int[] array,int lo ,int hi){
        if(lo>=hi){
            return ;
        }
        int index=partition(array,lo,hi);
        sort(array,lo,index-1);
        sort(array,index+1,hi); 
    }
  • 複雜度分析:

    1. 快速排序每次交換都是跳躍式的而不像冒泡每次都是相鄰交換,交換距離得到拓展,快排最壞時間複雜度為O(N^2), 與冒泡的一樣,因為快排比較與冒泡來說的優勢就是交換距離擴充套件,最差情況下優勢沒了,自然就與之一樣了。
    2. 快排的平均複雜度為O(NlogN)。
  • 演算法思想(分而治之):
    1. 古代君王統治大片國土常用分治法,如我們所知的分封制,郡縣制等等。採用分治法的原因很簡單,1. 國土面積大,2.君王自身精力有限。
    2. 同樣我們面對規模較為複雜的問題時,可以藉助於將其分為等價的規模較小的幾個模組而解決,分而治之與軟體設計的模組化思想有些類似,較大問題的解決都是基於較小問題的解決藉助於遞迴而解決的。