排序算法有不少種,這裏在複習和分析的基礎上,作一個本身的總結;算法
首先要知道有哪些排序算法,google一下,有云C語言7大經典排序算法(也有8大)。主要包括冒泡排序,快速排序,選擇排序,插入排序,希爾排序,歸併排序,堆排序,8大的還有基數排序。各有各的版本,代碼寫法也各不相同。因此這裏以整理思路爲先,代碼只是做爲本身的一個備份。shell
搞清楚的概念:穩定排序和不穩定排序,就看序列中兩個值相等的數,排完序以後的相對位置是否改變,若是改變了就不穩定。數組
內部排序和外部排序,只用到內存便可完成排序的就叫內部排序,外部排序由於序列比較長,用到了外部存儲。ide
算法好壞標準:時間複雜度和空間複雜度。分析T(n)=O(f(n))爲主,這個仍是比較簡單的理解一下就行,由於這種方法自己也是一種統計估計。性能
針對3中存儲結構,一、以一組連續的地址單元做爲存儲結構;二、以鏈表做爲存儲結構;三、和1同樣存儲,可是經過創建輔助表來進行排序。測試
插入類排序:直接插入排序,希爾排序;優化
第一個算法,直接插入算法,很簡單,假如咱們的數組是R[n+1],第一個做爲交換時用的中間變量;那麼R[1]做爲最初的有序區,從i=2開始不斷插入R[i],插入時跟有序區中的R[j]進行比較;R[0]在while循環中能夠做爲監視哨,以防下標變量j越界,避免了while循環檢測j是否越界,測試循環條件的時間能夠減小一半。ui
算法的時間複雜度爲O(n2);排序中最壞狀況就是全逆序,最好狀況,全正序;根據這樣的兩種狀況來判斷。google
希爾排序,多了一個增量數組,有選擇規則(使得增量值沒有除1以外的公因子)如5.3.1;按照增量的值進行多輪排序,使得序列趨於正序列和交換次數較少的序列;希爾排序其實就是插入排序的改進版本。spa
算法複雜度O(nlgn)
交換類排序:冒泡排序和快速排序
冒泡排序,想法很簡單,相鄰兩個元素比較,大的放後面,一趟一趟比,最後完成排序。快速排序就是對這一過程進行了優化;還有雙向冒泡法,改進算法,這裏不深刻了。冒泡排序算法複雜度O(n2)
快速排序,這裏首先要選取一個基準,通常都是一上來就吧R[0]做爲基準,大的放在右邊,小的放在左邊,造成兩個子序列,而後R[0]在中間,對兩個子序列繼續重複上一過程,直到序列裏面的個數爲1;從而能夠看出,這個算法能夠用遞歸。 算法複雜度O(n2);可是他是目前基於比較的內部排序方法中平均性能最好的。可是快讀排序不穩定。
選擇類排序:直接選擇排序,和直接插入排序做比較,其實差很少,不過這裏是選擇最小的一個做爲有序列的R[1],進行n-1趟排序。也是不穩定的,算法複雜度O(n2)
歸併排序:顧名思義,是合併,將一些較小的有序的序列進行合併從而成爲整個有序序列。他是穩定的排序,複雜度爲O(nlgn),通常應用時先採用直接插入排序獲得幾個有序序列,而後再進行歸併,這樣仍然是穩定的。
完了以後就是要把思路轉化爲程序。畢竟寫出程序的能力纔是最終要有的。
#include <stdio.h> #include <stdlib.h> #define n 8 typedef struct { int key; }rectype; rectype R[n+1]; void insertsort(rectype R[]) { int i,j; for(i=2;i<=n;i++) { if(R[i].key<R[i-1].key) { R[0]=R[i]; j=i-1; while(R[0].key<R[j].key) { R[j+1]=R[j--];//jiang guanjianzi dayu R[i].key de jilu houyi } R[j+1]=R[0]; } } } void shellsort(rectype R[],int d[],int t) { int i,j,k; for(k=0;k<t;k++) for(i=d[k]+1;i<=n;i++) if(R[i].key<R[i-d[k]].key) { R[0]=R[i]; j=i-d[k]; while(j>0&&R[0].key<R[j].key) { R[j+d[k]]=R[i]; j=j-d[k]; R[j-d[k]]=R[0]; } } } void bubblesort(rectype R[]) { int i,j,swap; for(i=1;i<n;i++) { swap=0; for(j=n;j>i;j--) if(R[j-1].key>R[j].key) { R[0]=R[j-1]; R[j-1]=R[j]; R[j]=R[0]; swap=1; } if(!swap) break; } } int partition(rectype R[],int low,int high) { rectype pivot=R[low]; while(low<high) { while(low<high&&R[high].key>=pivot.key) high--; if(low<high) R[low++]=R[high]; while(low<high&&R[low].key<=pivot.key) low++; if(low<high) R[high--]=R[low]; } R[low]=pivot; return low; } void quicksort(rectype R[],int s,int t) { int i; if(s<t) { i=partition(R,s,t); quicksort(R,s,i-1); quicksort(R,i+1,t); } } void selectsort(rectype R[],int m) { int i,j,k; rectype temp; for(i=1;i<m;i++) { k=i; for(j=i+1;j<=m;j++) if(R[j].key<R[k].key) k=j; if(k!=i) { temp=R[i]; R[i]=R[k]; R[k]=temp; } } } void merge(rectype R[],int low,int mid,int high) { int i,j,k; i=low;j=mid+1;k=0; rectype *R1=(rectype*)malloc((high-low+1)*sizeof(rectype)); if(!R1){printf("failed");exit(0);} while((i<=mid)&&(j<=high)) { if(R[i].key<=R[j].key) R1[k++]=R[i++]; else R1[k++]=R[j++]; } while(i<=mid) R1[k++]=R[i++]; while(j<=high) R1[k++]=R[j++]; for(k=0,i=low;i<high;k++,i++) R[i]=R1[k]; } void mergepass(rectype R[],int length) { int i=1; while(i+2*length-1<=n) { merge(R,i,i+length-1,i+2*length-1); i=i+2*length; } if((i+length-1)<n) { merge(R,i,i+length-1,n-1); } } void mergesort(rectype R[]) { int length; for(length=1;length<n;length*=2) mergepass(R,length); } int main() { int i; int d[]={5,3,1}; rectype R[]={{0},{12},{16},{23},{58},{68},{2},{7},{9}}; insertsort(R); for(i=1;i<=n;i++) printf("%d ",R[i].key); printf("\n"); shellsort(R,d,2); for(i=1;i<=n;i++) printf("%d ",R[i].key); printf("\n"); bubblesort(R); for(i=1;i<=n;i++) printf("%d ",R[i].key); printf("\n"); quicksort(R,1,8); for(i=1;i<=n;i++) printf("%d ",R[i].key); printf("\n"); selectsort(R,8); for(i=1;i<=n;i++) printf("%d ",R[i].key); printf("\n"); mergesort(R); for(i=1;i<=n;i++) printf("%d ",R[i].key); printf("\n"); }