直接插入排序:
直接插入排序通過線性搜索來確定待排序記錄的位置,在待排序記錄的前面形成一個單調的序列,對已排序記錄按照從大到小依次逐個進行比較。直到找到適合的位置(具體情況根據增減)。時間效率爲O(n^2),空間效率爲O(1),最好時間代價爲O(n),最差時間代價爲O(n^2)。直接插入排序對於基本有序的短序列排序的效率比較高,所以,之後幾種算法的優化都可以利用直接插入排序這一特性。
- void insertSort(int a[], int n){
- int i,j,tmp;
- if(n <= 1){return ;}
- for(i=1 ; i<n ; i++){
- tmp = a[i];
- j = i-1;
- while(j >= 0 && a[j] > tmp){
- a[j+1] = a[j];
- j--;
- }
- a[j+1] = tmp;
- }
- }
希爾排序:
先將序列分成若干子序列,而且要保證子序列中的記錄在原始的數組中不相鄰,而且間距相同,分別對這些小隊列進行排序。,然後減少記錄間距,減少子序列個數,將原始序列分成更大、更有序的序列,進行插入排序,直到最後間距爲一。希爾排序實質上是對於直接插入排序效率的一種折中,直接插入排序的適用短而基本有序的序列。希爾排序在排序的不同時期分別利用到了直接插入排序的優點。前期主要是採用排序短的序列,後期排列基本有序的長序列,可以說希爾排序,就是利用直接插入排序的優點,有針對性地對序列進行優化。時間複雜度:O(n^3/2)(跟序列的狀態無關),空間複雜度O(1)。還有這種排序是不穩定的,因爲他不是通過比較相鄰記錄實現插入的排序。
- void shellSort(int a[], int n){
- int i,delta;
- for(delta=n/2; delta > 0; delta /= 2){
- for(i = 0; i<delta; i++){
- insertModSort(&a[i],n-i,delta);
- }
- }
- insertModSort(a,n,1);
- }
- void insertModSort(int a[],int n,int delta){
- int i,j,tmp;
- for(i=delta; i<n ; i+=delta){
- tmp = a[i];
- j = i - delta;
- while(j>=0 && a[j] > tmp){
- a[j+delta] = a[j];
- j -= delta;
- }
- a[j+delta] = tmp;
- }
- }
直接選擇排序:
選擇排序的原理很簡單,就是掃描整個數組,找出最大值或最小值,然後把這個值與最前的記錄交換。接着從第二個記錄開始,掃描一遍數組,找出最大或最小值與第二個記錄交換,如此反覆,知道最後一個記錄爲止,整個數組有序。時間代價與記錄的初始排列無關爲O(n^2),空間代價爲O(1)。直接選擇排序,每一趟排序都是直接從線性剩餘記錄中查找最大記錄,沒有利用到之前的結果,故而效率較低。
- void selectSort(int a[], int n){
- int i,j,s,tmp;
- if(n <= 1)
- return;
- for(i=0; i<n; i++){
- s = i;
- for(j = i+1; j<n ; j++ ){
- if(a[s]>a[j]){
- s = j;
- }
- }
- tmp = a[i];
- a[i] = a[s];
- a[s] = tmp;
- }
- }
堆排序:
堆排序也是一種基於選擇的排序。它是採用一種樹形堆結構來儲存剩餘記錄,而樹形的堆結構的調整花費的時間是O(log(n)),因而比較高效。時間代價爲O(n*log(n)),空間代價剛好爲:O(1),排序主要分成兩步:
1.對所有記錄建最大堆,具體參照建堆的思路。
2.取出堆頂最大記錄與數組末端的數進行交換,然後調整堆,如此往復,直到堆建好爲止。
冒泡排序:
這是一種基於交換的排序,通過不停的比較相鄰記錄,然後實現基本有序。時間代價:O(n^2),空間代價:O(1)。
- void bubbleSort(int a[] , int n){
- int i,j,tmp;
- bool isSort = true;
- for(i=0;i<n;i++){
- for(j=n-1;j>i;j--){
- if(a[j-1] > a[j]){
- tmp = a[j];
- a[j] = a[j-1];
- a[j-1] = tmp;
- isSort = false;
- }
- }
- if( true ==isSort){
- break;
- }
- }
- }
快速排序:
這是我最喜愛的一種排序方法,快排對於隨機狀態的排序效率最高。這個一種基於分治法的排序算法,關鍵在於分、治、合,最終合併成一個可行解,時間效率爲O(n*log(n)),空間效率爲:O(log(n))。快排是一個不穩定的排序算法算法步驟如下:
1.從帶排記錄中選出一個記錄作爲軸值;
2.將剩餘記錄分割成左子序列L和右子序列R;
3.L中的所有記錄都小於軸值,R中的記錄都大於等於軸值;
4.對子序列L、R進行遞歸調用,直到子序列中只含有0或1個記錄的序列,退出遞歸調用。
- void quickSort(int a[], int l, int r){
- if(l >= r)
- return;
- int left = l,right = r;
- int pivot = a[l];
- while(true){
- while(l<r && a[r]>=pivot)
- r--;
- if(l<r){
- a[l] = a[r];
- l++;
- }
- while(l<r && a[l]<=pivot)
- l++;
- if(l<r){
- a[r] = a[l];
- r--;
- }
- if(l == r){
- a[l] = pivot;
- break;
- }
- }
- quickSort(a,left,l-1);
- quickSort(a,l+1,right);
- }
歸併排序:
這也是一種採用分治法的排序方法,它將原始序列劃分成兩個子序列,然後分別對子序列遞歸,最後將子序列合併,一個典型的分,治,合的思想。時間代價爲O(n*log(n)),空間代價爲O(n)。需要一個額外的臨時數組,與快排不同,歸併排序是一種穩定的排序。思路如下:
1.將原始序列分成兩個子序列;
2.分別對兩個子序列進行遞歸進行歸併排序;
3.將這兩個已經排好的子序列歸併到一個數組裏;
桶排序:
桶排序是完全不同於之前排序算法,他是基於收集的分配排序函數。因而他的時間代價可以達到O(m+n),空間代價爲O(m+n),m爲排序值的區間長度,因而是一個十分高效的排序算法,但是它的適用的範圍有限,它適用於區間跨度較小(m的值較小)的待排序列。
基數排序:
基數排序是基於桶排序的,我們可以認爲他是針對桶排序的一種優化,它將排序碼拆分成多個部分進行比較。如果要對0~9999之間的整數進行排序,那麼只需要將數字拆成個、十、百、千,分別對這四個進行桶排序,當然我們得采用低位優先法,方便我們的程序實現。時間代價爲O(d*(n+r)),空間代價爲O(n+r)。