1. 程式人生 > >最常用的排序:快速排序演算法

最常用的排序:快速排序演算法

快速排序(QuickSort)是一種很高效的排序演算法,但實際操作過程中不容易寫出十分正確具有健壯性的程式碼,所以我想講清這個問題,也能使自己理解更加深刻

演算法思想

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

演算法的程式碼我參考了阿哈磊的程式碼:http://bbs.ahalei.com/thread-4419-1-1.html
講的很透徹
給定一個序列5, 2, 8, 4, 22, 31, 0, 1, 9九個數字,來對九個數字排序

  • 第一步:找一個基準數(用來參考的數字),為了方便,就把第一個數字也就是5看成基準數

  • 第二步:一個小人從右往左找一個比基準數大的數字,然後另一個小人從左往右找一個比基準數小的數字(注意要先從右邊找,至於為什麼,後面再說)

  • 第二步完成後右邊找到一個數字是1,左邊找到一個數字是8,然後我們交換這兩個數字
    序列就變成了5, 2, 1, 4, 22, 31, 0, 8, 9

  • 然後繼續找 5, 2, 1, 4, 0, 31, 22, 8, 9
    當兩個小人碰頭,在0這個位置停下了,也就是兩邊查詢的陣列下標相等時,結束查詢,我們發現0左邊的數都是小於5的,右邊的數都是大於5的,然後我們把碰頭位置數字與基準數交換

    ,分成兩個序列
    左序列0,2,1,4,5
    右序列31,22,8,9
    然後繼續上面相同的操作(這裡是一個遞迴過程)

遞迴到最後,就能得到一個有序的序列

排序前序列:5 2 8 4 22 31 0 1 9
5 2 1 4 0 31 22 8 9
改變基準數:0 2 1 4 5 31 22 8 9
0 2 1 4 5 31 22 8 9
改變基準數:0 2 1 4 5 31 22 8 9
0 2 1 4 5 31 22 8 9
改變基準數:0 1 2 4 5 31 22 8 9
0 1 2 4 5 31 22 8 9
改變基準數:0 1 2 4 5 31 22 8 9
0 1 2 4 5 31 22 8 9
改變基準數:0 1 2 4 5 31 22 8 9
0 1 2 4 5 31 22 8 9
改變基準數:0 1 2 4 5 9 22 8 31
0 1 2 4 5 9 8 22 31
改變基準數:0 1 2 4 5 8 9 22 31
0 1 2 4 5 8 9 22 31
改變基準數:0 1 2 4 5 8 9 22 31
0 1 2 4 5 8 9 22 31
改變基準數:0 1 2 4 5 8 9 22 31
排序後序列:0 1 2 4 5 8 9 22 31

/*
快速排序演算法:
*/
#include<cstdio>
#include<iostream>
using namespace std; 
int a[10] = {5, 2, 8, 4, 22, 31, 0, 1, 9};
void print() {
  for(int i = 0; i < 9; i++)
    cout << a[i] << " ";
  cout << "\n";
}
void QuickSort(int left, int right) {
  int temp = a[left], i, j;
  i = left;
  j = right;
  if(i > j) return ;
  while(i != j) {//迴圈到兩個小人碰到為止 
    while(a[j] >= temp && i < j) j--;//右邊開始找,找到比基準數小的數 
    while(a[i] <= temp && i < j) i++;
    if(i < j) swap(a[i], a[j]);//交換兩個數 
  }  
  swap(a[left], a[i]);//改變基準數 
  print();
  QuickSort(left, i-1);  //遞迴過程
  QuickSort(i+1, right);
} 

int main() {
  print();
  QuickSort(0, 8);
  print();
} 

為什麼一定要先從右開始找?

不妨想想如果從左邊找

while(a[i] <= temp && i < j) i++;
while(a[j] >= temp && i < j) j–;

考慮一種情況,當i停下來的時候,找到一個大於基準數的數
接著j開始向左走,企圖尋找一個小於基準的數,但是存在i < j這個條件的限制,j有可能沒找到小於基準的數時就被迫停下來了,此時i==j的位置與基準數交換位置,結果就會出現錯誤