算法實驗:分治法合並排序(C++)


  這篇文章分兩部分來寫,第一部分寫代碼的實現過程,第二部分把實驗報告從頭到尾呈現出來。

  我習慣調試使用的編譯器是DEV C++,不是vs系列的,可能頭文件上有點區別。但是下面的報告是我放到vs里面測試過的,可以直接用,不影響。


 

第一部分:(解析)

  題目:隨機產生一個整型數組,然后用合並排序將該數組做升序排列,要求輸出排序前和排序后的數組。

 

題目分析:

  1. 需要隨機產生一個整數數組;
  2. 采用的算法是合並排序,也就是用歸並排序;
  3. 輸出排序后的數組。

 

  隨機產生一個整數數組:這個問題首先想到的是用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[]數組里的數依次輸出即可。


 

第二部分:(實驗報告)

(僅供參考!!!!!有誤麻煩指出,我會及時修改的。謝謝~)

 

實驗一 分治法合並排序

一、        實驗目的

  1. 掌握合並排序的基本思想。
  2. 掌握合並排序的實現方法。
  3. 學會分析算法的時間復雜度。
  4. 學會用分治法解決實際問題。

 

二、        實驗內容

隨機產生一個整型數組,然后用合並排序將該數組做升序排列,要求輸出排序前和排序后的數組。

 

三、        實驗環境

程序設計語言: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、注意通過遞歸的方式進行拆分。


免責聲明!

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



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