算法实验3最大子段和问题实验报告Word文档下载推荐.docx

上传人:b****7 文档编号:22391446 上传时间:2023-02-03 格式:DOCX 页数:16 大小:92.35KB
下载 相关 举报
算法实验3最大子段和问题实验报告Word文档下载推荐.docx_第1页
第1页 / 共16页
算法实验3最大子段和问题实验报告Word文档下载推荐.docx_第2页
第2页 / 共16页
算法实验3最大子段和问题实验报告Word文档下载推荐.docx_第3页
第3页 / 共16页
算法实验3最大子段和问题实验报告Word文档下载推荐.docx_第4页
第4页 / 共16页
算法实验3最大子段和问题实验报告Word文档下载推荐.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

算法实验3最大子段和问题实验报告Word文档下载推荐.docx

《算法实验3最大子段和问题实验报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《算法实验3最大子段和问题实验报告Word文档下载推荐.docx(16页珍藏版)》请在冰豆网上搜索。

算法实验3最大子段和问题实验报告Word文档下载推荐.docx

1.上机内容

给定有n个整数(可能有负整数)组成的序列(a1,a2,…,an),求改序列形如

的子段和的最大值,当所有整数均为负整数时,其最大子段和为0。

2.上机目的

(1)复习数据结构课程的相关知识,实现课程间的平滑过渡;

(2)掌握并应用算法的数学分析和后验分析方法;

(3)理解这样一个观点:

不同的算法能够解决相同的问题,这些算法的解题思路不同,复杂程度不同,解题效率也不同。

二、实验原理及基本技术路线图(方框原理图或程序流程图)

(1)分别用蛮力法、分治法和动态规划法设计最大子段和问题的算法;

蛮力法设计原理:

利用3个for的嵌套(实现从第1个数开始计算子段长度为1,2,3…n的子段和,同理计算出第2个数开始的长度为1,2,3…n-1的子段和,依次类推到第n个数开始计算的长为1的子段和)和一个if(用来比较大小),将其所有子段的和计算出来并将最大子段和赋值给summax1。

用了3个for嵌套所以时间复杂性为○(n3);

分治法设计原理:

1)、划分:

按照平衡子问题的原则,将序列(

,…,

)划分成长度相同的两个字序列(

)和(

)。

2)、求解子问题:

对于划分阶段的情况分别的两段可用递归求解,如果最大子段和在两端之间需要分别计算s1=

,s2=

,则s1+s2为最大子段和。

若然只在左边或右边,那就好办了,前者视s1为summax2,后者视s2osummax2。

3)、合并:

比较在划分阶段的3种情况下的最大子段和,取三者之中的较大者为原问题的解。

4)、时间复杂性分析:

f(n)=2*f(n/2)+○(n/2),最后为○(nlogn)。

动态规划法设计原理:

动态规划法求解最大字段和问题的关键是要确定动态规划函数。

由b(j)的定义,当b(j-1)>

0是,b(j)=b(j-1)+a,否则,b(j)=a。

可得如下递推式:

代码实现过程中只用了一个for,时间复杂性为:

○(n)

(2)对所设计的算法采用大O符号进行时间复杂性分析;

蛮力法时间复杂性为○(n3);

分治法时间复杂性为○(nlogn)

动态规划法时间复杂性为:

(3)上机实现算法,并用计数法和计时法分别测算算法的运行时间;

详情见运行结果。

(4)通过分析对比,得出自己的结论。

结论:

蛮力法只可以处理小理的数据。

当数据量超过10000时,由蛮力法要等很久才输出,所以数据量超过10000时,就比较分治法和动态规划法。

由实验结果可知,动态规划法所用的时间要少。

 

实验原理图:

三、所用仪器、材料(设备名称、型号、规格等或使用软件)

1台PC及VISUALC++6.0软件。

绘制流程图软件:

DiagramDesigner.

四、实验方法、步骤(或:

程序代码或操作过程)

部分重要代码说明:

#include<

time.h>

//时间的头文件

#include<

math.h>

//数学头文件

intgetMaxSum1(intiarray[],intn)/*蛮力法函数*/

intgetMaxSum2(intiarray[],intstartIndex,intendIndex)//分治法函数

intgetMaxSum3(intiarray[],intn)/*动态规划方法函数*/

intOUT_PRINTF()//输出最大字段求解的函数

intmain()//主函数

iostream>

usingnamespacestd;

/*蛮力法*/

intgetMaxSum1(intiarray[],intn)

{

intmaxSum=0;

//初始化maxSum

for(inti=0;

i<

n;

++i)//实现从第1个数开始计算子段长度为1,2,3…n的子段和

for(intj=i;

j<

++j)

{

inttmp=0;

//初始化tmp(子段和)

for(intk=i;

k<

=j;

++k)

tmp+=iarray[k];

}

if(tmp>

maxSum)//比较子段和,得出最大的子段和maxSum

maxSum=tmp;

}

returnmaxSum;

源程序代码:

/*分治递归方法*/

intgetMaxSum2(intiarray[],intstartIndex,intendIndex)

if(endIndex==startIndex)//只有一个元素

returniarray[startIndex];

if(endIndex-startIndex==1)//两个元素时

inttmp=iarray[startIndex]+iarray[endIndex];

tmp=tmp>

iarray[startIndex]?

tmp:

iarray[startIndex];

iarray[endIndex]?

iarray[endIndex];

returntmp;

//左边一半序列的最大子段和leftMaxSum

intleftMaxSum=getMaxSum2(iarray,startIndex,(startIndex+endIndex)/2);

//右边一半序列的最大子段和rightMaxSum

intrightMaxSum=getMaxSum2(iarray,(startIndex+endIndex)/2+1,endIndex);

ints1=0;

ints2=0;

inttmp=0;

for(inti=(startIndex+endIndex)/2;

i>

=startIndex;

--i)//左子段和

tmp=tmp+iarray[i];

s1)

s1=tmp;

tmp=0;

for(i=(startIndex+endIndex)/2+1;

=endIndex;

++i)//右子段和

s2)

s2=tmp;

intmiddleMaxSum=s1+s2;

intmaxSum=leftMaxSum>

rightMaxSum?

leftMaxSum:

rightMaxSum;

maxSum=maxSum>

middleMaxSum?

maxSum:

middleMaxSum;

returnmaxSum;

/*动态规划方法*/

intgetMaxSum3(intiarray[],intn)

intmaxSum=0;

intb=0;

for(inti=0;

++i)

if(b>

0)

b=b+iarray[i];

else

b=iarray[i];

maxSum)

maxSum=b;

}

intn,i,cho;

clock_tt1,t2,t3,t4,t5,t6;

cout<

<

"

****************************************\n"

;

**求最大字段和问题**\n"

endl;

/*********手动输入,请按1,随机输入请按2*********/\n"

cin>

>

cho;

请输入序列的长度"

n;

int*iarray=newint[n];

if(cho==2)

srand((unsigned)time(NULL));

//cout<

随机序列为:

for(i=1;

i<

=n;

i++)

{

iarray[i]=(rand()/13-1129);

//cout<

"

iarray[i];

}

else

请输入序列"

for(i=0;

t1=clock();

//使用蛮力法求解的开始时间

intmaxSum1=getMaxSum1(iarray,n);

t2=clock();

//蛮力法求解的结束时间

--------------------------------------------------\n"

蛮力法最大子段和为:

<

maxSum1<

endl;

时间:

float(t2-t1)/CLK_TCK<

//CLK_TCK

t3=clock();

//分治法求解的开始时间

intmaxSum2=getMaxSum2(iarray,0,n-1);

t4=clock();

//分治法求解的结束时间

分治法最大子段和为:

maxSum2<

float(t4-t3)/CLK_TCK<

t5=clock();

//动态规划法求解的开始时间

intmaxSum3=getMaxSum3(iarray,n);

t6=clock();

//动态规划法求解的结束时间

动态规划法最大子段和为:

maxSum3<

float(t6-t5)/CLK_TCK<

return0;

inti;

chara,y,Y,b;

OUT_PRINTF();

//调用输出函数

10;

cout<

是否继续输入?

Y/N"

a;

if(a=='

y'

||a=='

Y'

OUT_PRINTF();

if(a=='

n'

N'

return0;

五、实验过程原始记录(测试数据、图表、计算等)

测试程序:

输入选择的方式求最大子段和问题。

手动输入适合序列长度短的时候:

当要测试序列长度很大的时候,经过测试,蛮力法的输出时间太长,所以先省去蛮力法的测试。

当序列长度很大是,只调用动态规划法和分治法。

结果如下:

经过测试可知,动态规划法是最佳的选择。

六、实验结果、分析和结论(误差分析与数据处理、成果总结等。

其中,绘制曲线图时必须用计算纸或程序运行结果、改进、收获)

此次实验主要是设计了三种方法来求解最大子段和问题。

在此次实验中遇到过很多问题,如设置循环时,条件不合理,导致没有出来理想中得结果。

还有,为了得出每种方法求解的时间,添加了一个时间函数的头文件,程序中用到了clock()函数,clock()函数计算出来的是硬件滴答的数目,不是毫秒。

在TC2.0中硬件每18.2个滴答是一秒,在VC++6.0中硬件每1000个滴答是一秒。

C/C++中的计时函数是clock(),而与其相关的数据类型是clock_t。

故计算时间的公式为float(ti-ti-1)/CLK_TCK,其中clock_t是用来保存时间的数据类型,在time.h文件中,我们可以找到对它的定义。

用计算机解决复杂的问题,往往把一个大的、复杂的问题根据其功能划分为不同的模块,每一个模块完成一独立的功能.如果每一个模块用计算机语言来实现,那么当所有模块都实现时,即为对复杂问题的解决.最大子段和问题就是一具有独立功能的小模块,在很多大的问题中都涉及到此问题,用不同的算法解决此问题,并分析其优劣。

注:

教师必须按照上述各项内容严格要求,认真批改和评定学生成绩。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 化学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1