成员:林彦汝、张金
题目:
返回一个整数数组中最大子数组的和。
要求:
要求程序必须能处理1000 个元素;
每个元素是int32 类型的;
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。
(小伙伴主要负责程序分析,代码编程;我负责代码复审,代码测试计划。)
思路:
通过第一次求一个一维数组中最大子数组的和,在此基础上我们做了扩展。前面在程序中我们固定了数组的长度,默认为5,而这次则按题目要求扩展到1000,定义数值类型为int32。让程序随机产生1000个数,用同样的方法求子数组和的最大值。
刚看完题目时感觉不难,所以改动的地方不多,通过几次测试下来却发现了不少问题(在运行结果截图部分有分析说明)。
<span style="font-family: Microsoft YaHei; font-size: 16px;">#include<iostream.h> #include<stdlib.h> #define AMOUNT 1000 int main() { long int arr[AMOUNT]; long int arrCopy[AMOUNT]; long int max[AMOUNT]; int i,j; int n; int start,rear; //子数组的开始,结束 int mount=AMOUNT; for(i=0;i<mount;i++) { try { n=rand()%2; if(n==0) { arr[i]=rand(); arrCopy[i]=arr[i]; max[i]=arr[i]; } else { arr[i]=-rand(); arrCopy[i]=arr[i]; max[i]=arr[i]; } } catch(long int e) { cout<<"Long Inter=ger Exception!"<<endl; } } cout<<"Array :"<<endl; for(i=0;i<mount;i++) { cout<<arr[i]<<" "; if((i+1)%10==0) { cout<<endl; } } for(j=0;j<mount-1;j++) { for(i=j+1;i<mount;i++) { try { arr[j]=arr[j]+arr[i]; if(max[j]<arr[j]) { max[j]=arr[j]; rear=i+1; } } catch(long int e) { cout<<"Long Inter=ger Exception!"<<endl; } } } for(i=0;i<mount;i++) { if(max[0]<max[i]) { max[0]=max[i]; start=i+1; } } cout<<endl; cout<<"从第"<<start<<"个数"<<arrCopy[start-1]<<"开始"<<endl; cout<<"到第"<<rear<<"个数"<<arrCopy[rear-1]<<"结束"<<endl; cout<<"子数组和的最大值为: "<<max[0]<<endl; return 0; }
</span> |
运行结果:
(1)运行了几次(由于1000个数显示了100行,故只截取部分显示结果),由截图可以看到,很明显地随机产生的1000个数全部为正,没有负数。
(2)修改代码,通过随机产生0和1,来控制正数和负数的产生,避免只出现正数或者只出现负数的情况。
运行后又发现问题:因为有1000个数且数值都很大,我们并不能直接看出结果是否正确。
(3)完善程序,将子数组的位置找出来,再进行校验。
发现数值的范围还是很大,并且随机产生的数和最后相加的结果范围是不是超出了int32数据类型的范围(即是否数值越界),而C++本身在调试过程中是没有错误提示的,用异常处理来捕捉:
try
{
...
}
catch(long int e)
{
cout<<"Long Inter=ger Exception!"<<endl;
}
总结:
之前做的数组长度我们在测试时一般都填得很小,并且给每个元素的赋值也不超过两位数,甚至是固定了,都是为了方便直接找到一个和是最大的子数组,这都不能测试出程序哪里有不足,无论是数量还是数值的大小。通过随机产生的1000个数据我们发现了问题。因为已经把时间复杂度的概念给彻底忘了,这个程序也就没有考虑。
在调试中我的收获很大,以上截图都是调了很多次才改好了一个缺陷,因为数据很多,循环和嵌套就比较复杂,start和rear两个参数在开始添加时频繁出错,就先把数量改小,后运用单步调试到底看出错在哪一步,并且用异常处理来提示我们是否有数值越界等一些软件调试时不考虑的缺陷。