快速排序是基於分治模式的。
一.基本思路:
1.找出一個基準數;
2.重新排列數列,把比基準數小的放在前面,比基準數大的放在後面,分割結束後,基準數就是中間數,此操作也成爲分割操作;
3.遞歸的把被基準數分開的兩個序列重新排序。
快速排序是遞歸思想的經典運用。
該算法是由東尼·卡爾先生在1962年提出來的。
二.分解方法:
數組A[p…r]被劃分成兩個可能空的子數組A[p..q-1]<=A[q]<=A[q+1..r].
三.解決方法:
通過遞歸調用進行快速排序。
四.合併:
因爲兩個子數組是就地排序的,所以他們的合併不需要進行操作。
五.僞代碼:
版本一:
因爲選擇排序算法有很多種版本,此處首先選擇《算法導論》中的所用的那一版,即使用數組的最後一個元素作爲主元進行排序
QUICKSORT(A,p,r) If(p<r) Then q←PARTION(A,p,r) QUICKSORT(A,p,q-1) QUICKSORT(A,q+1,r) PARTION(A,p,r) x←A[r] i←p-1 forj←p to r-1 do if A[j]<=x then i←i+1 exchange A[i]A[j] exchange A[i+1]A[r] return i+1
六.源代碼實現:
#include<stdio.h> #include<stdlib.h> #define MAX 8 void exchange(int *x,int *y)//此處必須用指針實現,否則由於函數的拷貝不能改變調用函數的參數值 { int temp; temp=*x; *x=*y; *y=temp; } int partion(int v[],int p,int r) { int x=v[r]; int i=p-1; int j; for(j=p;j<=r-1;j++) { if(v[j]<x) { i++; exchange(&v[i],&v[j]); } } exchange(&v[i+1],&v[r]); return i+1; } void QuickSort(int v[],int p,int r) { int q=0; if(p<r) { q=partion(v,p,r); QuickSort(v,p,q-1); QuickSort(v,q+1,r); } } int main() { int v[MAX]; for(int i=0;i<MAX;i++) scanf("%d",&v[i]); QuickSort(v,0,MAX-1); for(int j=0;j<MAX;j++) printf("%d\t",v[j]); system("pause"); return 0; }
七.運行結果:
八.算法演示:
附:
版本二:
把數組的第一個元素作爲主元進行排序
僞代碼:
QUICKSORT
i←p
j←r
x←v[p]
if p<r
while i<j
while v[j]>=x
j-- //從右邊向左邊數找到第一個比主元小的數
if i<j
v[i]=v[j] //把找到的數賦給左邊被“挖掉的”數
i++
while v[i]<x
i++ //從左邊向右邊找,找到第一個比主元大的數
if i<j
v[j]=v[i] //再把找到的數賦給右邊“被挖掉的”數
j--
x←v[i]
QUICKSORT //再遞歸
源代碼實現:
#include<stdio.h> #include<stdlib.h> #define MAX 8 void QuickSort(int v[],int p,int r) { if (p<r) { int x=v[p]; int i=p; int j=r; while(i<j) { while(v[j]>=x&&i<j) j--; if(i<j) v[i++]=v[j]; while(i<j&&v[i]<x) i++; if(i<j) v[j--]=v[i]; } v[i]=x; QuickSort(v,p,i-1); QuickSort(v,i+1,r); } } int main() { int v[MAX]; for(int i=0;i<MAX;i++) scanf("%d",&v[i]); QuickSort(v,0,MAX-1); for(int j=0;j<MAX;j++) printf("%d\t",v[j]); system("pause"); return 0; }
運行結果
算法演示:
從上圖可以看出最終此數列被2分爲兩個子數列,然後以此類推進行遞歸排序,請讀者自己進行後面的步驟
九.總結:
關於快速排序的版本還有很多,但無非是選擇主元的方式和位置不同罷了,這裏只選擇兩個典型的方法進行初步介紹,至於算法性能等進階的問題,會在後面繼續進行詳細介紹。
版本一和版本二,理解任意一種即可,但個人認爲第二種似乎比較容易理解,且代碼也簡潔明瞭,值得學習。