經典的排序算法


這些天復習了排序這個模塊,排序算法在程序員的日常工作中是必不可少的,有時候我們不知不覺就用到了排序,這是因為高級語言系統已經比較完美的封裝和優化了排序算法,並且在筆試,面試等方面我們都能見到它的身影。下面結合那本大三的教材:嚴版的《數據結構》,來說一說這幾個經典的排序算法,如果有不對的歡迎指正!

首先我們還是先說基礎概念(按書上說的),萬變離不開概念,沒有概念沒有規矩,那可不行。

一、冒泡排序

二、直接選擇排序

三、直接插入排序

四、希爾排序

五、堆排序

六、歸並排序

七、快速排序

八、各種算法效率比拼

1:內部排序和外部排序(我們重點說內部排序(因為我們最常用到))

內排序:在排序的時間數據對象全部存放在內存的排序。
外排序:在排序的時間對象個數太多,不能同時存放在內存,根據排序的要求,不斷在內、外存之間移動。

2:排序的方法

按所排列(移動交換)的方式不同,可歸納為五類:插入排序、選擇排序、交換排序、歸並排序和分配排序(有的書上直接說基數)。
插入排序主要包括直接插入排序和希爾排序兩種;
選擇排序主要包括直接選擇排序和堆排序;
交換排序主要包括冒泡排序和快速排序;
歸並排序主要包括二路歸並(常用的歸並排序)。
分配排序主要包括箱排序和基數排序。

3:穩定性

穩定排序:假設在待排序的文件中,存在兩個或兩個以上的記錄具有相同的關鍵字,在用某種排序法排序后,若這些相同關鍵字的元素的相對次序仍然不變,則這種排序方法是穩定的。
冒泡,插入,基數,歸並屬於穩定排序;
選擇,快速,希爾,堆屬於不穩定排序。

4:圖表幫助大家記憶:

 各種排序算法
類別 排序方法 時間復雜度 穩定性
平均情況 最好情況 最壞情況
插入排序  直接插入
 O(n2)
 O(n)  O(n2)  穩定
 希爾排序
 O(n1.3)  O(n)  O(n2)  不穩定
 選擇排序
 直接選擇
 O(n2)  O(n2)  O(n2)  不穩定
 堆排序
 O(nlog2n)  O(nlog2n)  O(nlog2n)  不穩定
 交換排序
 冒泡排序
 O(n2)  O(n)  O(n2)  穩定
 快速排序
 O(nlog2n)  O(nlog2n)  O(n2)  不穩定
  歸並排序
O(nlog2n)  O(nlog2n)  O(nlog2n)  穩定
  基數排序
O(d(r+n))
O(d(n+rd))   O(d(r+n))   穩定
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

一、冒泡排序

冒泡排序也叫起泡排序,大家都知道,學C語言那會的循環結構就那這個做的例子,冒泡排序過程很簡單,但是效率太低。
1:簡要過程:
首先將一個記錄的關鍵字和第二個記錄的關鍵字比較若為逆序將兩個記錄交換,然后比較第二個記錄和第三個記錄的關鍵字....,直到n-1個記錄呢第n個記錄的關鍵字進行比較,上述過稱作一趟冒泡排序,然后進行第二趟,對n-1個記錄進行操作...(可以不安這種方法來,實際應用中可以逆序也可以正序)
2:排序效率:
如果開始的時候需要排序的元素是正序,則只要一趟,需要n-1次的關鍵字比較,如果為逆序要進行n(n-1)/2次的比較,所以時間復雜度是O(n2),所以效率超級的低,一般不建議使用
3:排序過程圖:
4:具體算法實現(可以有多種形式):
 1 //冒泡排序 
 2 void bubbling(int arr[], int n){
 3     int i, j, temp;
 4     for (j = 0; j < n - 1; j++){ 
 5         for (i = 0; i < n - 1 - j; i++){
 6             if(arr[i] > arr[i + 1]){
 7                 temp = arr[i];
 8                 arr[i] = arr[i + 1];
 9                 arr[i + 1] = temp;
10             }
11         }
12     } 
13 }

 

二、直接選擇排序

是一種選擇排序,總的來說交換的少,比較的多,如果排序的數據是字符串的話比建議使用這種方法。

1:簡要過程:

首先找出最大元素,與最后一個元素交換(arr[n-1]),然后再剩下的元素中找最大元素,與倒數第二個元素交換....直到排序完成。

2:排序效率:

一趟排序通過n-1次的關鍵字比較,從n-i-1個記錄中選擇最大或者最小的元素並和第i個元素交換,所以平均為n(n-1)/2,時間復雜度為O(n2),也不是個省油的燈,效率還是比較低。

3:排序過程圖:(選擇小元素,圖片來源百度搜索)

4:具體算法實現:

 1 //直接選擇排序 
 2 void directDialing(int arr[], int n){  3     int i,j,k,num;  4     for(i = 0; i < n; i++){  5         num = 0;  6         for(j = 0; j < n-i; j++){  7             if(arr[j] > arr[num]){  8                 num = j;  9  } 10  } 11         k = arr[n-i-1]; 12         arr[n-i-1] = arr[num]; 13         arr[num] = k; 14  } 15 }

 

三、直接插入排序

是一種簡單的排序方法,算法簡潔,容易實現

1:簡要過程:

每步將一個待排序元素,插入到前面已經排序好的元素中,從而得到一個新的有序序列,直到最后一個元素加入進去即可。

2:排序效率:

空間上直接插入排序只需要一個輔助空間,時間上:花在比較兩個關鍵字的大小和移動記錄,逆序時比較次數最大:(n+2)(n-1)/2,平均:n2/4,所以直接插入排序時間復雜度也是O(n2)

3:排序過程圖:

4:具體算法實現:

 1 //直接插入排序
 2 void  insert(int arr[], int n){  3     int m,i,k;  4     for(i = 1; i < n; i++){  5         m = arr[i];  6         for(k = i-1; k >= 0; k--){  7             if(arr[k] > m){  8                 arr[k+1] = arr[k];  9             }else{ 10                 break; 11  } 12  } 13         arr[k+1] = m; 14  } 15 }
 
四、希爾排序
希爾排序,也叫縮小增量排序,是一種插入排序,和前三種不一樣它在時間效率上有很大的改進,所以這種排序方法才是我們需要重點學習和掌握的,但是凡事都有利弊,容易的排序算法算法簡單,但是效率低下,反過來復雜的排序算法算法復雜,但是效率及其的出色。

 1:簡要過程:

選擇一個增量序列a1,a2,…,ak,其中ai>aj,ak=1;按增量序列個數k,對序列進行k 趟排序;每趟排序,根據對應的增量ai,將待排序列分割成若干長度為m 的子序列,分別對各子表進行直接插入排序。僅增量因子為1 時,整個序列作為一個表來處理,表長度即為整個序列的長度。
說白了其實就是:先取一個正整數d1<n,把所有序號相隔d1的數組元素放一組,組內進行直接插入排序;然后取d2<d1,重復上述分組和排序操作;直至di=1,即所有記錄放進一個組中排序為止。

2:排序效率:

希爾排序的效率的確不低,大量的研究說時間復雜度為O(n3/2)(書上說的在大量的試驗基礎上推出的)感覺有點玄乎,但是希爾排序效率確實很高,在后面我寫的有一個效率比拼大家可以看看。

3:排序過程圖:

 
 4:具體算法實現:
 1 //希爾排序 
 2 void Heer(int arr[], int n){  3     int i,j,k,num;  4     k = n/2;  5     while(k > 0){  6         for(i = k; i < n; i++){  7             num = arr[i];  8             for(j = i - k;j >= 0; j -= k){  9                 if(arr[j] > num){ 10                     arr[j+k] = arr[j]; 11                 }else{ 12                     break; 13  } 14  } 15             arr[j+k] = num; 16  } 17         k = k/2; 18  } 19 } 

 

五、堆排序

先說說堆的定義:n個元素的序列{k1,k2,. . . kn}當且僅當滿足以下條件時稱之為堆:

ki <= k2i              ki >= k2i

ki <= k2i+1          ki >= k2i+1

若將這樣的序列對用的一維數組看成一個完全二叉樹則堆的定義看出:完全二叉樹非終節點的值均不大於(不小於)其左右兩個孩子的節點值。

大頂堆和小頂堆:堆頂元素取最小值的是小頂堆,取最大值的是大頂堆。

1:簡要過程:

(1) 建堆:對初始序列建堆的過程,就是一個反復進行篩選的過程。n 個結點的完全二叉樹,則最后一個結點是第(既是程序中的n * 2 +1)個結點的子樹。篩選從第個結點為根的子樹開始,該子樹成為堆。之后向前依次對各結點為根的子樹進行篩選,使之成為堆,直到根結點。

(2) 調整堆:k個元素的堆,輸出堆頂元素后,剩下k-1 個元素。將堆底元素送入堆頂(最后一個元素與堆頂進行交換),堆被破壞,其原因僅是根結點不滿足堆的性質。將根結點與左、右子樹中較小元素的進行交換。若與左子樹交換:如果左子樹堆被破壞,即左子樹的根結點不滿足堆的性質,則重復調整堆,.若與右子樹交換,如果右子樹堆被破壞,即右子樹的根結點不滿足堆的性質。則重復調整堆。對不滿足堆性質的子樹進行上述交換操作,直到葉子結點,堆被建成。

2:排序效率:

堆排序的方法對記錄較少的文件並不值得提倡,但對於數據較大的文件還是很有效的,時間主要花在初始建堆和交換元素后調整堆上。對深度為k的堆比較算法最多為2(k-1)次,含有n個元素深度為h的堆時總共進行的關鍵字比較不超過4n,由此可見最壞的情況下,時間復雜度為O(nlogn)並且僅需要一個輔助控間,速度已經是相當快了。

3:排序過程圖(圖片來源百度,幫助理解):

4:具體算法實現:

 1 //堆調整 
 2 void adjust(int arr[], int n, int length){  3     int max,b;  4     while(n * 2 +1 <= length){//說明存在左節點 
 5         max = n * 2 + 1;  6         if(n * 2 + 2 <= length){//說明存在右節點 
 7             if(arr[max] < arr[n * 2 + 2]){  8                 max = n * 2 + 2; //跟新最小的值 
 9  } 10  } 11         if(arr[n] > arr[max]){ 12             break;//順序正確,不需要再調整 
13         }else{ 14             b = arr[n]; 15             arr[n] = arr[max]; 16             arr[max] = b; 17             n = max; 18  } 19  } 20 } 21 
22 //堆排序 
23 void stack(int arr[], int length){ 24     int i,k,m = 0; 25     for(i = length/2-1; i >=0; i--){ 26         adjust(arr,i,length-1); 27  } 28     //調整堆
29     for(i = length-1 ;i >= 0; i--){ 30         //調整后把最后一個和第一個交換,每次調整少一個元素,依次向前 
31         k = arr[i]; 32         arr[i] = arr[0]; 33         arr[0] = k; 34         adjust(arr,0,i-1); 35  } 36 }

 

六、歸並排序

將兩個和兩個以上的排序表合成一個新的有序表,歸並排序是分治法思想運用的一個典范。

1:簡要過程:

 將有 n個對象的原始序 列看作 n個有序子列,每個序列的長度為1,從第一個子序列開始,把相鄰的子序列兩兩合並得到[n/2]個長度為2或者是1的歸並項,(如果n為奇數,則最后一個有序子序列的長度為1),稱這一個過程為一趟歸並排序。

然后重復上述過程指導得到一個長度為n的序列為止。

2:排序效率:

 一趟歸並排序的操作是:調用[n/2b]次算法,整個過程需要[log2n]趟,課件歸並排序時間復雜度是O(logn)

3:排序過程圖:

 

4:具體算法實現:

 1 //歸並排序合並函數 
 2 void mergeSoft(int a[], int first, int mid, int last, int temp[]){  3     int i = first, j = mid + 1;  4     int m = mid,   n = last;  5     int k = 0;  6     while (i <= m && j <= n){  7         if (a[i] <= a[j]){  8             temp[k++] = a[i++];  9         }else{ 10             temp[k++] = a[j++]; 11  } 12  } 13     while (i <= m){ 14         temp[k++] = a[i++]; 15  } 16     while (j <= n){ 17         temp[k++] = a[j++]; 18  } 19     
20     for (i = 0; i < k; i++){ 21         a[first + i] = temp[i]; 22  } 23 } 24 
25 //歸並排序遞歸拆分函數
26 void mergerSelf(int arr[], int left, int right, int arrTmp[]){ 27     if(left < right){ 28         int center = (left + right)/2; 29  mergerSelf(arr, left, center, arrTmp); 30         mergerSelf(arr, center+1, right, arrTmp); 31  mergeSoft(arr, left, center, right, arrTmp); 32  } 33 } 34 //歸並排序 
35 void merger(int arr[], int n){ 36     int *arrTmp = new int[n]; 37     mergerSelf(arr, 0, n - 1, arrTmp); 38     delete[] arrTmp; 39 } 

 

七、快速排序

快速排序是一種交換排序,說白了就是一種對起泡排序的改進,不過改進了不少,快速排序被認為是最好的一種排序算法(同量級別)。

1:簡要過程:

選擇一個基准元素,我們稱之為中樞,通常選擇第一個元素或者最后一個元素,中樞的選擇很重要,直接影響排序的性能,這是因為如果代排序列有序,快速排序就退化為冒泡排序。將序列分割成左右兩個序列。其中一部分記錄的元素值均比基准元素值小。另一部分記錄的 元素值比基准值大。一趟排序的具體做法將兩個附設指針left和right,然后分別對這兩部分記錄用同樣的方法繼續進行排序,直到整個序列有序。

2:排序效率:

 在所有同級別的排序算法中其平均性能最好O(nlogn)。如果代排序列有序,快速排序就退化為冒泡排序,效率及其低下,這個可以在下面的效率比拼圖中體現出來逆序的時候快速排序非常慢,效率很低下。所以可以在中樞的選擇上優化可以選着最左邊和最右邊中間的元素取其平均值即可。

3:排序過程圖:

 

4:具體算法實現:

 1 //快速排序的元素移動 
 2 int fastSort(int arr[], int left, int right){  3     int center = (left+right)/2;  4     int num = arr[center]; //記錄中樞點的位置,這里選擇最左邊點當做中樞點 
 5     while(left < right){  6         //比樞紐小的移動到左邊 
 7         while(left < right && arr[right] >= num){  8             right--; //一直到有一個元素小於所選關鍵中樞為止 
 9  } 10         arr[left] = arr[right]; 11         
12         while(left < right && arr[left] <= num){ 13             left++; //一直到有一個元素大於所選關鍵中樞為止 
14  } 15         arr[right] = arr[left]; //關鍵字入列 
16  } 17     arr[left] = num; 18     return left; 19 } 20 
21 //快速排序遞歸划分
22 int fastSortSelf(int arr[], int left, int right){ 23     if(left < right){ 24         int lowLocation = fastSort(arr,left,right); //第一個指針的位置 
25         fastSortSelf(arr,left,lowLocation - 1); 26         fastSortSelf(arr,lowLocation + 1,right); 27  } 28 } 29 
30 //快速排序 
31 void fast(int arr[], int n){ 32     fastSortSelf(arr,0,n-1); 33     //記錄時間
34 } 

 

八、各種算法效率比拼

下面是我自己寫的一個算法比拼,測試數據有100-50000都有,分為最壞情況(逆序->正序)和隨機情況(隨機->正序),測試數據會因為機器的不同而不同,我的是win8,64, 4G,cpu2.5,歡迎大家測試

說明兩點:要注意時間的得到方法,需要引入的頭文件包括

1 #include <iostream>
2 #include <iomanip> 
3 #include <stdlib.h>
4 #include <time.h>
1 end_time = clock(); 
2 程序。。。。
3 times = static_cast<double>(end_timestart_time)/CLOCKS_PER_SEC*1000;cout <<right ; cout <<setw(7) <<times<<"ms";

下面是程序代碼:

 1 #include <iostream>
 2 #include <iomanip> 
 3 #include <stdlib.h>
 4 #include <time.h>
 5 using namespace std;  6 
 7 clock_t start_time, end_time;  8 int times;  9 
 10 void printfArr(int arr[], int n){  11     for(int i = 0; i < n; i++){  12         cout<<arr[i]<<" ";  13  }  14 }  15 
 16 //冒泡排序 
 17 void bubbling(int arr[], int n){  18     start_time = clock();  19     int i, j, temp;  20     for (j = 0; j < n - 1; j++){  21            for (i = 0; i < n - 1 - j; i++){  22                if(arr[i] > arr[i + 1]){  23                   temp = arr[i];  24                      arr[i] = arr[i + 1];  25                      arr[i + 1] = temp;  26  }  27  }  28  }  29     end_time = clock();  30     times = static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000;  31     cout <<right ; cout <<setw(7) <<times<<"ms";  32 }  33 
 34 //直接選擇排序 
 35 void directDialing(int arr[], int n){  36     start_time = clock();  37     int i,j,k,num;  38     for(i = 0; i < n; i++){  39         num = 0;  40         for(j = 0; j < n-i; j++){  41             if(arr[j] > arr[num]){  42                 num = j;  43  }  44  }  45         k = arr[n-i-1];  46         arr[n-i-1] = arr[num];  47         arr[num] = k;  48  }  49     end_time = clock();  50     times = static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000;  51     cout <<right ; cout <<setw(7) <<times<<"ms";  52 }  53 
 54 //直接插入排序 (On2)
 55 void  insert(int arr[], int n){  56     start_time = clock();  57     int m,i,k;  58     for(i = 1; i < n; i++){  59         m = arr[i];  60         for(k = i-1; k >= 0; k--){  61             if(arr[k] > m){  62                 arr[k+1] = arr[k];  63             }else{  64                 break;  65  }  66  }  67         arr[k+1] = m;  68  }  69     end_time = clock();  70     times = static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000;  71     cout <<right ; cout <<setw(7) <<times<<"ms";  72 }  73 
 74 //希爾排序 
 75 void Heer(int arr[], int n){  76     start_time = clock();  77     int i,j,k,num;  78     k = n/2;  79     while(k > 0){  80         for(i = k; i < n; i++){  81             num = arr[i];  82             for(j = i - k;j >= 0; j -= k){  83                 if(arr[j] > num){  84                     arr[j+k] = arr[j];  85                 }else{  86                     break;  87  }  88  }  89             arr[j+k] = num;  90  }  91         k = k/2;  92  }  93     end_time = clock();  94     times = static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000;  95     cout <<right ; cout <<setw(7) <<times<<"ms";  96 }  97 
 98 //堆調整 
 99 void adjust(int arr[], int n, int length){ 100     int max,b; 101     while(n * 2 +1 <= length){//說明存在左節點 
102         max = n * 2 + 1; 103         if(n * 2 + 2 <= length){//說明存在右節點 
104             if(arr[max] < arr[n * 2 + 2]){ 105                 max = n * 2 + 2; //跟新最小的值 
106  } 107  } 108         if(arr[n] > arr[max]){ 109             break;//順序正確,不需要再調整 
110         }else{ 111             b = arr[n]; 112             arr[n] = arr[max]; 113             arr[max] = b; 114             n = max; 115  } 116  } 117 } 118 
119 //堆排序 
120 void stack(int arr[], int length){ 121     start_time = clock(); 122     int i,k,m = 0; 123     for(i = length/2-1; i >=0; i--){ 124         adjust(arr,i,length-1); 125  } 126     //調整堆
127     for(i = length-1 ;i >= 0; i--){ 128         //調整后把最后一個和第一個交換,每次調整少一個元素,依次向前 
129         k = arr[i]; 130         arr[i] = arr[0]; 131         arr[0] = k; 132         adjust(arr,0,i-1); 133  } 134     end_time = clock(); 135     times = static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000; 136     cout <<right ; cout <<setw(7) <<times<<"ms"; 137 } 138 
139 //歸並排序合並函數 
140 void mergeSoft(int a[], int first, int mid, int last, int temp[]){ 141     int i = first, j = mid + 1; 142     int m = mid,   n = last; 143     int k = 0; 144     while (i <= m && j <= n){ 145         if (a[i] <= a[j]){ 146             temp[k++] = a[i++]; 147         }else{ 148             temp[k++] = a[j++]; 149  } 150  } 151     while (i <= m){ 152         temp[k++] = a[i++]; 153  } 154     while (j <= n){ 155         temp[k++] = a[j++]; 156  } 157     
158     for (i = 0; i < k; i++){ 159         a[first + i] = temp[i]; 160  } 161 } 162 
163 //歸並排序遞歸拆分函數
164 void mergerSelf(int arr[], int left, int right, int arrTmp[]){ 165     if(left < right){ 166         int center = (left + right)/2; 167  mergerSelf(arr, left, center, arrTmp); 168         mergerSelf(arr, center+1, right, arrTmp); 169  mergeSoft(arr, left, center, right, arrTmp); 170  } 171 } 172 //歸並排序 
173 void merger(int arr[], int n){ 174     start_time = clock(); 175     int *arrTmp = new int[n]; 176     mergerSelf(arr, 0, n - 1, arrTmp); 177     delete[] arrTmp; 178     //記錄時間 
179     end_time = clock(); 180     times = static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000; 181     cout <<right ; cout <<setw(7) <<times<<"ms"; 182 } 183 
184 //快速排序的元素移動 
185 int fastSort(int arr[], int left, int right){ 186     int center = (left+right)/2; 187     int num = arr[center]; //記錄中樞點的位置,這里選擇最左邊點當做中樞點 
188     while(left < right){ 189         //比樞紐小的移動到左邊 
190         while(left < right && arr[right] >= num){ 191             right--; //一直到有一個元素小於所選關鍵中樞為止 
192  } 193         arr[left] = arr[right]; 194         
195         while(left < right && arr[left] <= num){ 196             left++; //一直到有一個元素大於所選關鍵中樞為止 
197  } 198         arr[right] = arr[left]; //關鍵字入列 
199  } 200     arr[left] = num; 201     return left; 202 } 203 
204 //快速排序遞歸划分
205 int fastSortSelf(int arr[], int left, int right){ 206     if(left < right){ 207         int lowLocation = fastSort(arr,left,right); //第一個指針的位置 
208         fastSortSelf(arr,left,lowLocation - 1); 209         fastSortSelf(arr,lowLocation + 1,right); 210  } 211 } 212 
213 //快速排序 
214 void fast(int arr[], int n){ 215     start_time = clock(); 216     fastSortSelf(arr,0,n-1); 217     //記錄時間
218     end_time = clock(); 219     times = static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000; 220     cout <<right ; cout <<setw(7) <<times<<"ms"; 221 } 222 
223 int main(){ 224     cout<<"\n****************************整數最壞(逆序)測試***********************\n\n"; 225     cout<<"數據量 冒泡 選擇 插入 希爾 堆 歸並 快速\n"; 226     int size;   //記錄每個測試數量 
227     int tmpNum; //記錄臨時數 
228     int arr1[8] = {49,38,65,97,76,13,27,49}; 229     //測試數據的各個范圍 
230     int nums[6] = {100,1000,5000,10000,30000,50000}; 231     /*
232  printfArr(arr1,8); 233  printf("\n"); 234  fast(arr1,8); 235  printfArr(arr1,8);*/
236 
237     for(int p = 0; p < 6; p++){ 238         size = nums[p]; 239         int arrs1[size],arrs2[size],arrs3[size],arrs4[size],arrs5[size],arrs6[size],arrs7[size]; 240         cout<<left; cout <<"n="<<setw(6)<<size; 241         //產生有序數 
242         for(int m = 0; m < size; m++){ 243             int tmpNum = size - m; 244             arrs1[m] = tmpNum; 245             arrs2[m] = tmpNum; 246             arrs3[m] = tmpNum; 247             arrs4[m] = tmpNum; 248             arrs5[m] = tmpNum; 249             arrs6[m] = tmpNum; 250             arrs7[m] = tmpNum; 251  } 252         bubbling(arrs1,size);     //冒泡排序法
253         directDialing(arrs2,size);//直接選擇排序
254         insert(arrs3,size);       //直接插入排序
255         Heer(arrs4,size);         //希爾排序
256         stack(arrs5,size);        //堆排序 
257         merger(arrs6,size);       //歸並排序 
258         fast(arrs7,size);         //快速排序
259         cout<<"\n"; 260  } 261     
262     //*****************隨機數測試法******************
263     int number; 264     int nlong; //數據量 
265     cout<<"\n******************************隨機數測試*******************************\n\n"; 266     cout<<"數據量 冒泡 選擇 插入 希爾 堆 歸並 快速\n"; 267     for(int r = 0; r < 6; r++){ 268         size = nums[r]; 269         int rands1[size],rands2[size],rands3[size],rands4[size],rands5[size],rands6[size],rands7[size]; 270         //產生測試隨機數 
271  srand((unsigned) time(NULL)); 272         for (int rd = 0; rd < size; rd++){ 273             tmpNum = rand() % size; 274             rands1[rd] = tmpNum; 275             rands2[rd] = tmpNum; 276             rands3[rd] = tmpNum; 277             rands4[rd] = tmpNum; 278             rands5[rd] = tmpNum; 279             rands6[rd] = tmpNum; 280             rands7[rd] = tmpNum; 281  } 282         //輸出測試數據量 
283         cout<<left; cout <<"n="<<setw(6)<<size; 284         //依次調用各個排序函數 
285         bubbling(rands1,size);     //冒泡排序法
286         directDialing(rands2,size);//直接選擇排序
287         insert(rands3,size);       //直接插入排序
288         Heer(rands4,size);         //希爾排序
289         stack(rands5,size);        //堆排序 
290         merger(rands6,size);       //歸並排序 
291         fast(rands7,size);         //快速排序
292         cout<<"\n"; 293  } 294 }
 
運行結果如圖:沒有優化快速排序(逆序中樞選擇第一個)前的效果,n=30000的時候遞歸太深出錯,只能把n=10000。
 
 
運行結果如圖:優化后快速排序(逆序中樞選擇第一個最后一個的中間值)的效果,n=50000的時候,只用了4ms
 
 
  因為時間關系,寫的不全,比如:算法具體的時間復雜度計算方法沒有詳細寫出(有時間會補充完整),還有就是快速排序的改進程序,歸並排序的合並細節沒有說。反正是寫每個程序都遇到很多問題,所有程序都可以編譯運行,希望大家提出寶貴意見。
  轉載請注明出處!
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM