一、最大连续子数组和(最大子段和)
问题背景
给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
问题分析
当给定一组数组时,从i=0开始,令j=i,j每加1,就得到一个当前子段和,若大于sum,将其赋值为sum,累计相加,直到数组的最后一个数字,可得在i=0时的最大子段;进行循环,最后通过不断地比较而得最大子段和。以下将以流程图的形式给出该题的具体思路,同时也更便于单元测试。
程序代码:https://coding.net/u/llwang/p/AddMax/git/tree/master
二、单元测试中不同覆盖方法的比较
1.语句覆盖:语句覆盖是最起码的结构覆盖要求,语句覆盖要求设计的测试用例,使得程序中每条语句至少被执行一次。
2.判定覆盖:判定覆盖又称为分支覆盖,它要求程序中每个判定至少有一次为真值,有一次为假值。
3.条件覆盖:要求设计足够多的测试用例,使得判定中的每个条件获得各种可能的结果,即每个条件至少有一次为真值,有一次为假值。
4.条件/判定覆盖:要求使得判定中每个条件的所有可能结果至少出现一次,每个判定本身所有可能结果也至少出现一次。
5.组合覆盖:要求设计足够多的测试用例,使得每个判定中条件结果的所有可能组合至少出现一次。
三、单元测试
1.程序清单
#include<iostream>
using namespace std;
int MaxAdd(int n, int arr[]){
int sum = 0;
for (int i = 0; i < n; i++){
int thisSum = 0;
for (int j = i; j < n; j++){
thisSum += arr[j];
if (thisSum > sum)
sum = thisSum;
}
}
if (sum < 0) sum = 0;
return sum;
}
int main(){
int n, sum = 0;
int arr[100];
cin >> n;
for (int i = 0; i < n; i++){
cin >> arr[i];
}
sum = MaxAdd(n, arr);
cout << sum << endl;
system("pause");
return 0;
}
2.流程图
3.测试代码
#include "stdafx.h"
#include "CppUnitTest.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
int MaxAdd(int n, int arr[]){
int sum = 0;
for (int i = 0; i < n; i++){
int thisSum = 0;
for (int j = i; j < n; j++){
thisSum += arr[j];
if (thisSum > sum)
sum = thisSum;
}
}
if (sum < 0) sum = 0;
return sum;
}
namespace UnitTest1
{
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
// TODO: 在此输入测试代码
int arr[5] = { -1, 2, -1, 0, -2};
int sum = MaxAdd(5, arr);
Assert::AreEqual(2, sum);
}
TEST_METHOD(TestMethod2)
{
// TODO: 在此输入测试代码
int arr[5] = { -1, 2, 4, 3, 2 };
int sum = MaxAdd(5, arr);
Assert::AreEqual(11, sum);
}
TEST_METHOD(TestMethod3)
{
// TODO: 在此输入测试代码
int arr[5] = { -2, 1, 0, 1, -1 };
int sum = MaxAdd(5, arr);
Assert::AreEqual(2, sum);
}
TEST_METHOD(TestMethod4)
{
// TODO: 在此输入测试代码
int arr[5] = { -2, 1, 1, 2, 3 };
int sum = MaxAdd(5, arr);
Assert::AreEqual(7, sum);
}
};
}
4.样例分析
我选择的是组合覆盖,即每个条件的所有可能列出,并进行组合,经过分析,我选择了四组用例,覆盖了所有的组合情况。程序包含两个判断条件,有四种组合,如(1)thisSum>=sum,thisSum<=sum;
(2)sum>=0,sum<=0
因可由四种组合写出四组测试样例:
thisSum>=sum&&sum>0;thisSum>=sum&&sum<=0;
thisSum<=sum&&sum>0;thisSum<sum&&sum<=0.
5.总结
上次作业我学会了Junit单元测试,这次作业因为想用C++编程,于是又学会了visual studio自带的单元测试,因此我觉得平时多给自己一些学习的机会,俗话说技多不压身。同时,自己设计样例进行单元测试,这使我们对程序可能出现的各种情况都很清楚。单元测试在编程中起着至关重要的作用,但是我们的练习还远远不够,为了给以后更好的工作做铺垫,一定要多多练习单元测试,全面的,更好的设计测试案例,以提高工作效率。