分治算法实验(用分治法实现归并排序算法)

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法分析与设计实验报告 第 二 次实验
姓 名 时 间 实 验 名 称 实 验 目 的 实 验 原 理 10.17上午 地点 工训楼309 学号 班级
分治算法实验(用分治法实现归并排序算法)
通过上机实验,要求掌握分治算法的问题描述、算法设计思想、程序设计。 给定任意几组数据,利用分治法的思想,将数据进行排序并将排好的数 据进行输出。 程序思路: (1)简单的将原始序列划分为两个子序列; (2)分别对每一个子序列递归排序; (3)最后将排好序的子序列合并成一个有序序列。 ① 先解决小规模的问题。 ② 将问题分解,将数组分为两个小的数组。 ③ 递归的解各子问题, 将中分解的两个小的数组再进行以上两个步骤 最后都化为小规模问题。 ④ 将各子问题的解进行合并最终得到原问题的解。
{ int max=a[0],min=a[0]; int i,j,n; cout<<"请输入数据规模:"<<endl; for(j=0;j<5;j++) { cin>>n; ran(a,n); clock_t start,end,over; //计算程序运行时间的算法 start=clock(); end=clock(); over=end-start; start=clock(); for(i=1;i<n;i++) { if(a[i]>max) max=a[i]; if(a[i]<min) min=a[i]; } cout<<max<<" "<<min<<endl; end=clock(); printf("The time is %6.3f",(double)(end-startover)/CLK_TCK); //显示运行时间 } system("pause"); return 0; }
完整代码(非递归方法)
#include<iostream> #include<time.h> #include<iomanip> using namespace std; void ran(int *input,int n) { int i; srand(time(0)); for(i=0;i<n;i++) input[i]=rand(); input[i]='\0'; } int a[1000000]; int main() //随机生成数组元素函数
关 键 代 码
//调用合并函数,将子序列合并,实现整个数列的有序 for(int h=left;h<=right;h++) //将临时有序的数组复制回原数组 { a[h]=b[h]; } } }
没有输出排序序列的结果:
测 试 结 果
输出排序序列的结果:
实 验 心 得
对于归并排序,在之前的数据结构已经学过了,本来以为代码实现起来会比较简单,可 是情况并不是这样的。对于分治法这个算法,我存在的困难主要是我明白分治过程是如 何的,但是却很难和代码练习起来,我对于递归过程还是很不清楚,所以代码实现起来 还是很困难。不过幸好我之前有提前准备,提前将归并排序仔细的研究过了,所以还是 磕磕巴巴的将代码实现,也因为这两个分治法的实验,使我更加深入了解了分治法,对 于递归过程也更加明白,相信在自己练习几次之后,能够掌握这个函数。 观察上面两个不同的实现方法所花费的时间,我们可以看到,采用非递归的方法实现, 所花费的时间比利用分治法花费的时间多,为什么会出现这样的结果,我们可以知道在 分治法需要比较的次数比非递归方法多,甚至是多得多,所以它所花费的时间也多,所 以对于这种ห้องสมุดไป่ตู้最大值最小值的问题,利用非递归的方法相对会好一点。 助教签名
//将两个子序列合并,排序成一个有序的序列 { int i=low; int j=mid+1; int k=low; while((i<=mid)&&(j<=high)) //两两比较,将较小的数放在临时 的数组中 { if(A[i]<=A[j]) { B[k++]=A[i++]; } else { B[k++]=A[j++]; } } if(i>mid) //如果最后左半边子序列已经全部排完,就将右 边子序列剩下的元素直接复制到临时的数组中 { for(int last=j;last<=high;last++) { B[k++]=A[last]; } } else //如果最后右半边子序列已经全部排完,就将左边子序列 剩下的元素直接复制到临时的数组中 { for(int last=i;last<=mid;last++) { B[k++]=A[last]; } } } void mergesort(int a[],int b[],int left,int right) //分治法实 现归并排序,利用递归实现
B[k++]=A[i++]; } else { B[k++]=A[j++]; } } if(i>mid) //如果最后左半边子序列已经全部排完,就 将右边子序列剩下的元素直接复制到临时的数组中 { for(int last=j;last<=high;last++) { B[k++]=A[last]; } } else //如果最后右半边子序列已经全部排完,就将左边 子序列剩下的元素直接复制到临时的数组中 { for(int last=i;last<=mid;last++) { B[k++]=A[last]; } } } void mergesort(int a[],int b[],int left,int right) //分 治法实现归并排序,利用递归实现 { if(left<right) //如果序列中元素超过一个才会进行划分 { int mid=(left+right)/2; //将序列从中位数地方划分为两个子序列 mergesort(a,b,left,mid); // 对左半边子序列递归调用自身,将子序列变成有序 mergesort(a,b,mid+1,right); //对右边子序列递归调用自身,将子序列变成有序 merge(a,b,left,mid,right);
{ if(left<right) //如果序列中元素超过一个才会进行划分 { int mid=(left+right)/2; //将序列从中位数地方划分为两 个子序列 mergesort(a,b,left,mid); // 对左半边子序列递归调用自身,将子序列变成有序 mergesort(a,b,mid+1,right); //对右边子序列递归调用自 身,将子序列变成有序 merge(a,b,left,mid,right); //调用合并函数,将子序列 合并,实现整个数列的有序 for(int h=left;h<=right;h++) //将临时有序的数组复制 回原数组¦ { a[h]=b[h]; } } } void ran(int *input,int n) //数组随机生成函数 { int i; srand(time(0)); for(i=0;i<n;i++) input[i]=rand(); input[i]='\0'; } int a[1000000]; int b[1000000]; int main() { int n; cout<<"请输入要归并排序的记录个数:"<<endl; for(int j=0;j<5;j++) { cin>>n; ran(a,n); //生成数组
clock_t start,end,over; //计算程序运行时间的算法 start=clock(); end=clock(); over=end-start; start=clock(); mergesort(a,b,0,n-1); //调用分治法函数 for(int i=0;i<n;i++) { cout<<a[i]<<" "; } cout<<endl; end=clock(); printf("The time is %6.3f",(double)(end-startover)/CLK_TCK);//输出运行时间 } system("pause"); return 0; }
实 验 步 骤
void merge(int A[],int B[],int low,int mid,int high) //将两个子序列合并排序成一个有序的序列 { int i=low; int j=mid+1; int k=low; while((i<=mid)&&(j<=high)) //两两比较,将较小的数放在临时的数组中 { if(A[i]<=A[j]) {
实 验 比 较 实 验 得 分
附录: 完整代码(分治法)
#include<iostream> #include<time.h> #include<iomanip> using namespace std; void merge(int A[],int B[],int low,int mid,int high)
相关文档
最新文档