实验目的
分治法实现合并排序,得到不同规模数据实验的时间对比,并进行时间复杂度分析。
实验原理
使用分治法,根据不同的输入用例n,准确输出这n个随机数从小到大排列后的序列。
合并排序算法思想:将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成要求的排好序的集合。
实验步骤
①创建两个数组。
②不断将原数组从中间分开,然后放入两个数组中。
③将两个数组中的元素逐一进行比较放入原数组中。
关键代码
//合并函数,q为切分点,array数组就是随机数的数组
void Merge(int *_Array, int p, int q, int r)
{//p:第0个;r:第n-1个数,q:第(r + p)/2个数
int len1=q-p+1;
int len2=r-q;
int *L=new int[len1+1];//用动态数组储存左边的数
int *R=new int[len2+1];//用动态数组储存右边的数
for (int i=0;i<len1;i++)
{// 把Array数组左边的数放入L数组
L[i]=_Array[p+i];
}
for(int j=0;j<len2;j++)
{// 把Array数组右边的数放入R数组
R[j]=_Array[q+1+j];
}
L[len1]=R[len2]=INT_MAX;//定义无穷大
int i=0,j=0;
for(int k=p;k<=r;k++)
{
if(L[i]<R[j])
{//小的放左边,大的放右边
_Array[k]=L[i];
i++;
}
else
{
_Array[k]=R[j];
j++;
}
}
}
//归并排序
void MergeSort(int _Array[],int p,int r)
{
if(p<r)
{//p:第0个;r:第n-1个数。数组至少要有两个数据
int q;
q=(r+p)/2;//拆分两组
MergeSort(_Array,p,q);//拆分第0个到第 (r + p) / 2个 ,即拆分左半部分
MergeSort(_Array,q+1,r);//拆分第(r + p) / 2个到第r个 ,即拆分右半部分
Merge(_Array,p,q,r);//调用合并函数,从第0个到第n-1个排好
}
}
时间复杂度分析
合并排序主要考虑两个函数的时间花销,合并函数Merge()和归并排序函数
MergeSort()。Merge ()代码中有2个长度为n的非嵌套循环,所以时间复杂度则为O(n);调用MergeSort()函数划分两部分,那每一小部分排序好所花时间则为 T[n/2],而最后把这两部分有序的数组合并成一个有序的数组Merge()函数所花的时间为 O(n),根据公式T[n] = 2T[n/2] + O(n),T[n] = O( nlogn );所以为O( nlogn )。
实验心得
通过这次实验,我学习了合并排序的分治算法,熟悉了随机数生成方法和文件读写操作。
分析实验结果发现合并排序算法消耗的时间非常短。
完整代码
分治法排序
#include<iostream>
#include<fstream>
#include<windows.h>
#include<ctime>
using namespace std;
//合并函数,q为切分点,array数组就是随机数的数组
void Merge(int *_Array, int p, int q, int r)
{//p:第0个;r:第n-1个数,q:第(r + p)/2个数
int len1=q-p+1;
int len2=r-q;
int *L=new int[len1+1];//用动态数组储存左边的数
int *R=new int[len2+1];//用动态数组储存右边的数
for (int i=0;i<len1;i++)
{// 把Array数组左边的数放入L数组
L[i]=_Array[p+i];
}
for(int j=0;j<len2;j++)
{// 把Array数组右边的数放入R数组
R[j]=_Array[q+1+j];
}
L[len1]=R[len2]=INT_MAX;//定义无穷大
int i=0,j=0;
for(int k=p;k<=r;k++)
{
if(L[i]<R[j])
{//小的放左边,大的放右边
_Array[k]=L[i];
i++;
}
else
{
_Array[k]=R[j];
j++;
}
}
}
//归并排序
void MergeSort(int _Array[],int p,int r)
{
if(p<r)
{//p:第0个;r:第n-1个数。数组至少要有两个数据
int q;
q=(r+p)/2;//拆分两组
MergeSort(_Array,p,q);//拆分第0个到第 (r + p) / 2个 ,即拆分左半部分
MergeSort(_Array,q+1,r);//拆分第(r + p) / 2个到第r个 ,即拆分右半部分
Merge(_Array,p,q,r);//调用合并函数,从第0个到第n-1个排好
}
}
int main()
{
ifstream in;
in.open("input.txt");
ofstream out;
int n;
in>>n;
int Array[n];
for (int i=0;i<n;i++){in>>Array[i];}
in.close();
clock_t start,end;
start=clock();
MergeSort(Array,0,n-1);
end=clock();
printf("时间:%fms\n",(double)(end-start)/CLK_TCK);
out.open("output.txt");
out<<"排序后的数组为:";
for(int j=0;j<n;j++)
{
out<<Array[j]<<" ";
}
out.close();
return 0 ;
}
随机数生成
#include<stdlib.h>
#include<time.h>
#include<fstream>
#include<iostream>
using namespace std;
int main(){
int n;
cin>>n;
ofstream out("input.txt");
out<<n<<'\n';
srand((unsigned)time(NULL));
for(int i=0;i<n;i++){
out<<rand()<<' ';
if((i+1)%10==0) out<<'\n';
}
out.close();
return 0;
}