這篇文章分兩部分來寫,第一部分寫代碼的實現過程,第二部分把實驗報告從頭到尾呈現出來。
我習慣調試使用的編譯器是DEV C++,不是vs系列的,可能頭文件上有點區別。但是下面的報告是我放到vs里面測試過的,可以直接用,不影響。
第一部分:(解析)
題目:隨機產生一個整型數組,然后用合並排序將該數組做升序排列,要求輸出排序前和排序后的數組。
題目分析:
- 需要隨機產生一個整數數組;
- 采用的算法是合並排序,也就是用歸並排序;
- 輸出排序后的數組。
隨機產生一個整數數組:這個問題首先想到的是用rand()函數(c語言和c++我記得好像不太一樣,c++是用rand()函數),rand()函數不需要參數,是來返回一個從0到最大隨機數的任意整數,最大隨機數的大小通常是固定的一個大整數。寫法格式是這樣的:
1 #include<cstdlib> //使用rand()函數必要的頭文件 2 3 //獲取a~b之間的一個隨機數可以表示為: 4 a + rand() % n //a是起始值,n是整數的范圍 5 //或者 6 a + rand() % (b-a+1) // a是起始值,b是最大值 7 //如果要0~1之間的小數,可以先取得0~10的整數,然后除以10就可以得到隨機到十分位的隨機小數,百分位、千分位同理。
然后rand()函數會涉及到用time.h.頭文件,使用srand(time(0))來獲取當前時間,使隨機數發生器隨機化這些內容,這里就不探討了,主要解決掉問題是能把某一個數到另一個數的隨機數產生即可,代碼如下:
1 int n; 2 cout << "輸入產生的數組個數:"; 3 cin >> n; 4 cout << endl; 5 6 int *Array = new int[n]; //定義的是動態數組 7 cout << "產生的隨機數組為:"; 8 9 for (int i = 0; i < n; i++) { 10 Array[i] = (rand()%(100-0+1))+0; //產生0-100的整數 11 cout<<Array[i]<<" "; //產生后一個一個輸出來 12 } 13 cout<<endl;
歸並排序:百度很多博客都在詳細介紹歸並,這里簡單說明一下:先把已知數組分成兩組,然后兩組中分別再分成兩組,直到每一組都只有一個數據,然后再合並的同時排序,直到都合並起來就ok。需要寫出兩個函數:
MergeSort() —>歸並函數,用遞歸的方式把數據細分,最后合並。
Merge() —>合並函數。
代碼如下:
1 //合並函數 2 void Merge(int *_Array, int p, int q, int r) {// p:第0個;r:第n-1個數,q:第(r + p) / 2個數 3 int len1 = q - p + 1; 4 int len2 = r - q; 5 int *L = new int[len1 + 1];//用動態數組儲存左邊的數 6 int *R = new int[len2 + 1];//用動態數組儲存右邊的數 7 8 for (int i = 0; i < len1; i++) {// 把Array數組左邊的數放入L數組 9 L[i] = _Array[p + i]; 10 } 11 12 for (int j = 0; j < len2; j++) {// 把Array數組右邊的數放入R數組 13 R[j] = _Array[q + 1 + j]; 14 } 15 L[len1]=R[len2]=INT_MAX; //定義無窮大 16 int i = 0, j = 0; 17 for (int k = p; k <= r; k++) { 18 if (L[i] < R[j]) {//小的放左邊,大的放右邊 19 _Array[k] = L[i]; 20 i++; 21 } 22 else { 23 _Array[k] = R[j]; 24 j++; 25 } 26 } 27 }
1 // 歸並排序 2 void MergeSort(int _Array[], int p, int r) { 3 if (p < r) {//p:第0個;r:第n-1個數。數組至少要有兩個數據 4 int q; 5 q = (r + p) / 2;//拆分兩組 6 MergeSort(_Array , p , q);//拆分第0個到第 (r + p) / 2個 ,即拆分左半部分 7 MergeSort(_Array , q+1 , r);//拆分第(r + p) / 2個到第r個 ,即拆分右半部分 8 Merge(_Array , p , q , r);//調用合並函數,從第0個到第n-1個排好 9 } 10 }
輸出排序后的數組:調用MergeSort()函數后直接在主函數中用for循環把Array[]數組里的數依次輸出即可。
第二部分:(實驗報告)
(僅供參考!!!!!有誤麻煩指出,我會及時修改的。謝謝~)
實驗一 分治法合並排序
一、 實驗目的
- 掌握合並排序的基本思想。
- 掌握合並排序的實現方法。
- 學會分析算法的時間復雜度。
- 學會用分治法解決實際問題。
二、 實驗內容
隨機產生一個整型數組,然后用合並排序將該數組做升序排列,要求輸出排序前和排序后的數組。
三、 實驗環境
程序設計語言:c++
編程工具:microsoft visual studio 2010
四、 程序代碼
1 #include <stdafx.h> 2 #include "iostream" 3 #include "time.h" 4 #include "stdlib.h" 5 using namespace std; 6 //合並函數 7 void Merge(int *_Array, int p, int q, int r) {// p:第0個;r:第n-1個數,q:第(r + p) / 2個數 8 int len1 = q - p + 1; 9 int len2 = r - q; 10 int *L = new int[len1 + 1];//用動態數組儲存左邊的數 11 int *R = new int[len2 + 1];//用動態數組儲存右邊的數 12 13 for (int i = 0; i < len1; i++) {// 把Array數組左邊的數放入L數組 14 L[i] = _Array[p + i]; 15 } 16 17 for (int j = 0; j < len2; j++) {// 把Array數組右邊的數放入R數組 18 R[j] = _Array[q + 1 + j]; 19 } 20 L[len1]=R[len2]=INT_MAX; //定義無窮大 21 int i = 0, j = 0; 22 for (int k = p; k <= r; k++) { 23 if (L[i] < R[j]) {//小的放左邊,大的放右邊 24 _Array[k] = L[i]; 25 i++; 26 } 27 else { 28 _Array[k] = R[j]; 29 j++; 30 } 31 } 32 } 33 // 歸並排序 34 void MergeSort(int _Array[], int p, int r) { 35 if (p < r) {//p:第0個;r:第n-1個數。數組至少要有兩個數據 36 int q; 37 q = (r + p) / 2;//拆分兩組 38 MergeSort(_Array , p , q);//拆分第0個到第 (r + p) / 2個 ,即拆分左半部分 39 MergeSort(_Array , q+1 , r);//拆分第(r + p) / 2個到第r個 ,即拆分右半部分 40 Merge(_Array , p , q , r);//調用合並函數,從第0個到第n-1個排好 41 } 42 } 43 44 int main() { 45 int n; 46 cout << "輸入產生的數組個數:"; 47 cin >> n; 48 cout << endl; 49 int *Array = new int[n]; 50 cout << "產生的隨機數組為:"; 51 srand((unsigned)time(0)); 52 53 for (int i = 0; i < n; i++) { 54 Array[i] = (rand()%(100-0+1))+0; 55 //cin>>; 56 cout<<Array[i]<<" "; 57 } 58 cout<<endl; 59 60 MergeSort(Array,0,n-1); 61 62 cout << "排序后的數組為:"; 63 for(int j = 0;j<n;j++){ 64 cout<<Array[j]<<" "; 65 } 66 // int a; 67 // cin>>a; 68 return 0 ; 69 }
五、 實驗結果截圖
六、 實驗總結
1、通過本次實驗學到了分治算法,分治法的設計思想是:將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。
2、二路歸並排序主要思路是按照將一組數據不斷二次拆分,直到拆分成每組數據只有一個數,最后相鄰的數合並起來為一組數,認為它是一組有序的數。
3、注意通過遞歸的方式進行拆分。