算法一直是編程的基礎,而排序算法是學習算法的開始,排序也是數據處理的重要內容。所謂排序是指將一個無序列整理成按非遞減順序排列的有序序列。排列的方法有很多,根據待排序序列的規模以及對數據的處理的要求,可以采用不同的排序方法。那么就整理下網上搜索的資料,按自己的理解,把C語言的8大排序算法列出來。
普通意義上,排序算法可以分為三大類:
1 交換類排序法
2 插入類排序法
3 選擇類排序法
一.交換類排序法
所謂交換排序法是指借助數據元素之間互相交換進行排序的方法。冒泡排序與快速排序法都屬於交換類排序方法。
1、冒泡排序(BubbleSort)
冒泡排序的基本概念:
依次比較相鄰的兩個數,將小數放在前面,大數放在后面。即在第一趟:首先比較第1個和第2個數,將小數放前,大數放后。然后比較第2個數和第3個數,將小數放前,大數放后,如此繼續,直至比較最后兩個數,將小數放前,大數放后。至此第一趟結束,將最大的數放到了最后。在第二趟:仍從第一對數開始比較(因為可能由於第2個數和第3個數的交換,使得第1個數不再小於第2個數),將小數放前,大數放后,一直比較到倒數第二個數(倒數第一的位置上已經是最大的),第二趟結束,在倒數第二的位置上得到一個新的最大數(其實在整個數列中是第二大的數)。如此下去,重復以上過程,直至最終完成排序。由於在排序過程中總是小數往前放,大數往后放,相當於氣泡往上升,所以稱作冒泡排序。
實現:
外循環變量設為i,內循環變量設為j。假如有10個數需要進行排序,則外循環重復9次,內循環依次重復9,8,...,1次。每次進行比較的兩個元素都是與內循環j有關的,它們可以分別用a[j]和a[j+1]標識,i的值依次為1,2,...,9,對於每一個i,j的值依次為1,2,...10-i。
圖示:
C語言實現:
1 void Bublesort(int a[],int n) 2 { 3 int i,j,k; 4 for(j=0;j<n;j++) /* 氣泡法要排序n次*/ 5 { 6 for(i=0;i<n-j;i++) /* 值比較大的元素沉下去后,只把剩下的元素中的最大值再沉下去就可以啦 */ 7 { 8 if(a[i]>a[i+1]) /* 把值比較大的元素沉到底 */ 9 { 10 k=a[i]; 11 a[i]=a[i+1]; 12 a[i+1]=k; 13 } 14 } 15 } 16 }
性能分析:
若記錄序列的初始狀態為"正序",則冒泡排序過程只需進行一趟排序,在排序過程中只需進行n-1次比較,且不移動記錄;反之,若記錄序列的初始狀態為"逆序",則需進行n(n-1)/2次比較和記錄移動。因此冒泡排序總的時間復雜度為O(n*n)。
博客園中,有一篇博文是關於冒泡算法的優化,可以看下,兩種優化:
白話經典算法系列之一 冒泡排序的三種實現
2、快速排序(Quicksort)
基本思想:
快速排序是對冒泡排序的一種改進。由C. A. R. Hoare在1962年提出。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然后再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。

如無序數組[6 2 4 1 5 9]
a),先把第一項[6]取出來,
用[6]依次與其余項進行比較,
如果比[6]小就放[6]前邊,2 4 1 5都比[6]小,所以全部放到[6]前邊
如果比[6]大就放[6]后邊,9比[6]大,放到[6]后邊,//6出列后大喝一聲,比我小的站前邊,比我大的站后邊,行動吧!霸氣十足~
一趟排完后變成下邊這樣:
排序前 6 2 4 1 5 9
排序后 2 4 1 5 6 9
b),對前半拉[2 4 1 5]繼續進行快速排序
重復步驟a)后變成下邊這樣:
排序前 2 4 1 5
排序后 1 2 4 5
前半拉排序完成,總的排序也完成:
排序前:[6 2 4 1 5 9]
排序后:[1 2 4 5 6 9]
1 int partition(int *data,int low,int high) 2 3 { 4 int t = 0; 5 6 t = data[low]; 7 8 while(low < high) 9 10 { while(low < high && data[high] >= t) 11 12 high--; 13 14 data[low] = data[high]; 15 16 while(low < high && data[low] <= t) 17 18 low++; 19 20 data[high] = data[low]; 21 22 } 23 24 data[low] = t; 25 26 return low; 27 28 } 29 30 void sort(int *data,int low,int high) //快排每趟進行時的樞軸要重新確定,由此進 //一步確定每個待排小記錄的low及high的值 31 32 { if(low >= high) 33 34 return ; 35 36 int pivotloc = 0; 37 38 pivotloc = partition(data,low,high); 39 40 sort(data,low,pivotloc-1); 41 42 sort(data,pivotloc+1,high); 43 44 }
性能分析
快速排序的時間主要耗費在划分操作上,對長度為k的區間進行划分,共需k-1次關鍵字的比較。
最壞情況是每次划分選取的基准都是當前無序區中關鍵字最小(或最大)的記錄,划分的結果是基准左邊的子區間為空(或右邊的子區間為空),而划分所得的另一個非空的子區間中記錄數目,僅僅比划分前的無序區中記錄個數減少一個。時間復雜度為O(n*n)
在最好情況下,每次划分所取的基准都是當前無序區的"中值"記錄,划分的結果是基准的左、右兩個無序子區間的長度大致相等。總的關鍵字比較次數:O(nlgn)
盡管快速排序的最壞時間為O(n2),但就平均性能而言,它是基於關鍵字比較的內部排序算法中速度最快者,快速排序亦因此而得名。它的平均時間復雜度為O(nlgn)。
這里有一個視頻比較形象地說明了這兩個有趣的排序算法:http://www.tudou.com/programs/view/htKY1-Rj9ZE/?resourceId=0_06_02_99