本節介紹乙個非常優秀且最常用的排序演算法,快速排序演算法。這個演算法極其重要,初學者一定要掌握。
快速排序尤其適用於對大資料的排序,它的高速和高效無愧於「快速」兩個字。雖然說它是「最常用」的,可對於初學者而言,用它的人卻非常少。因為雖然很快,但它也是邏輯最複雜、最難理解的演算法,因為快速排序要用到遞迴和函式呼叫。
快速排序所採用的思想是分治的思想。所謂分治,就是指以乙個數為基準,將序列中的其他數往它兩邊「扔」。以從小到大排序為例,比它小的都「扔」到它的左邊,比它大的都「扔」到它的右邊,然後左右兩邊再分別重複這個操作,不停地分,直至分到每乙個分割槽的基準數的左邊或者右邊都只剩乙個數為止。這時排序也就完成了。
所以快速排序的核心思想就是將小的往左「扔」,將大的往右「扔」,只要能實現這個,就與快速排序的思想吻合。從初學者的角度,「小的往左扔大的往右扔」首先能想到的往往是小的往前插,大的往後插。這確實是乙個思路,但我們知道,陣列是不擅長插入的。這種思路雖然能吻合快速排序的思想,但實現起來就不是「快速」排序,而是「慢速」排序了。所以這種方法是不可行的。於是就有了下面的「舞動演算法」。
「舞動演算法」的思想是用交換取代插入,大大提高了排序的速度。下面首先詳細地講解一下陣列快速排序的過程。
假設序列中有 n 個數,將這 n 個數放到陣列 a 中。「舞動演算法」中一趟快速排序的演算法是: 1. 設定兩個變數 i、j,排序開始的時候:i=0,j=n–1。
2. 以陣列第乙個元素為關鍵資料,賦給變數 key,即 key=a[0]。
3. 從 j 開始向前搜尋,即由後開始向前搜尋(j--),找到第乙個小於 key 的值 a[j],將 a[j] 和 a[i] 互換。
4. 然後再從 i 開始向後搜尋,即由前開始向後搜尋(++i),找到第乙個大於 key 的 a[i],將 a[i] 和 a[j] 互換。
5. 重複第 3、4 步,直到 i=j。此時就能確保序列中所有元素都與 key 比較過了,且 key 的左邊全部是比 key 小的,key 的右邊全部是比 key 大的。
第一輪比較後序列就以 key 為中心分成了左右兩部分,然後分別對左右兩部分分別遞迴執行上面幾個步驟,直到排序結束。
下面列舉乙個簡單的例子,比如對如下陣列 a 中的元素使用快速排序實現從小到大排序:
35 12 37 -58 54 76 22
1) 首先分別定義 low 和 high 用於儲存陣列第乙個元素的下標和最後乙個元素的下標,即 low=0,high=6。
2) 然後定義 key 用於存放基準數,理論上該基準數可以取序列中的任何乙個數。此處就取陣列的第乙個元素,即把 a[low] 賦給 key。
3) 然後 key 和 a[high] 比較,即 35 和 22 比較,35>22,則它們互換位置:
22 12 37 -58 54 76 35
4) 然後 low++==1,key 和 a[low] 比較,即 35 和 12 比較,12<35,則不用互換位置;繼續 low++==2,然後 key 和 a[low] 比較,即 35 和 37 比較,37>35,則它們互換位置:
22 12 35 -58 54 76 37
5) 然後 high--==5,key 和 a[high] 比較,即 35 和 76 比較,35<76,則不用互換位置;繼續 high--==4,然後 key 和 a[high] 比較,即 35 和 54 比較,35<54,則不用互換位置;繼續 high--==3,然後 key 和 a[high] 比較,即 35 和 -58 比較,35>–58,則它們互換位置:
22 12 -58 35 54 76 37
6) 然後 low++==3,此時 low==high,第一輪比較結束。從最後得到的序列可以看出,35 左邊的都比 35 小,35 右邊的都比 35 大。這樣就以 35 為中心,把原序列分成了左右兩個部分。接下來只需要分別對左右兩個部分分別重複上述操作就行了。
對於人類而言,這個過程確實比前面的排序演算法複雜。但對於計算機而言,這個過程卻沒那麼複雜。下面來寫乙個程式:
# include void swap(int *, int *); //函式宣告, 交換兩個變數的值
void quicksort(int *, int, int); //函式宣告, 快速排序
int main(void)
; quicksort(a, 0, 20); /*引用起來很簡單, 0為第乙個元素的下標, 20為最後乙個元素的下標*/
printf("最終排序結果為:\n");
for (i=0; i<21; ++i)
printf("\n");
return 0;
}void swap(int *p, int *q)
void quicksort(int *a, int low, int high)
while (low < high) //該while迴圈結束一次表示比較了一輪
if (key > a[high])
while (low < high && key >= a[low])
if (key < a[low])
}quicksort(a, i, low-1); //用同樣的方式對分出來的左邊的部分進行同上的做法
quicksort(a, low+1, j); //用同樣的方式對分出來的右邊的部分進行同上的做法
}
最後附上氣泡排序的**進行對比
#include "stdio.h"
int main(void)
; int n; //存放陣列a中元素的個數
int i; //比較的輪數
int j; //每輪比較的次數
int buf; //交換資料時用於存放中間資料
n = sizeof(a) / sizeof(a[0]) - 1; /*a[0]是int型, 佔4位元組, 所以總的位元組數除以4等於元素的個數*/
for (i = 0; ia[j + 1])
}} for (i = 0; iprintf("\n");
system("pause");
return 0;
}
排序 快速排序,C 實現
本文 的github位址 基本思想 快速排序 是對 氣泡排序 的改進。基本原理 基於分治法,在待排線性表中取乙個元素pivot作為樞軸值,通過一趟排序將待排線性表劃分為獨立的兩部分,第一部分的所有元素小於pivot,第二部分的所有元素大於等於pivot,pivot位於其最終位置。遞迴對兩個子表做快速...
快速排序 c 實現
快速排序思想 基於分治策略,對氣泡排序的一種改進。對於要排序的乙個序列,從中選一值進行排序,將其放入到正確的位置position。然後以position為界,對左右兩部分再做排序。直到劃分的長度為1。步驟 設有一待排序的序列 1.分別設定low hight指向序列的最左端 最右端 從序列中選乙個進行...
快速排序(C 實現)
include using namespace std void swap int a,int b int sort int begin,int end if beginwhile beginif begin return begin void quicksort int begin,int end...