问题: 给定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。
--引用《百度百科》
你们能够参照算法导论第四章或者是这里或者个人Github,来查看具体如何实现,这里主要给你们展现功能函数模块和测试该函数模块html
//max_array.cpp #include<iostream> #include "gtest/gtest.h" using namespace std; /** *功能函数 *@author Stone *version 1.0 */ //获得最大中子数组 int FIND_MAX_CROSSING_SUBARRAY(int a[], int low, int mid, int high) { int sum = 0; int left_sum, right_sum; int max_left, max_right; int i, j; left_sum = right_sum = -1000;//使左右子数组和为无穷小,假设数组和不会小于-1000 for(i = mid; i >= low; i--) { sum = sum + a[i]; if(sum > left_sum) { left_sum = sum; max_left = i; } } sum = 0; for(j = mid+1; j <= high; j++) { sum = sum +a[j]; if(sum > right_sum) { right_sum = sum; max_right = j; } } low = max_left; high = max_right; sum = left_sum + right_sum; return sum; } //传进去数组,数组的低位序号,高位序号,返回最大子数组 int FIND_MAXIMUM_SUBARRAY(int a[], int low, int high) { int left_sum, right_sum, cross_sum; //低位序号和高位序号相同 if(low == high) { return a[low]; } else { int mid; mid = (low + high)/2; left_sum = FIND_MAXIMUM_SUBARRAY(a, low, mid);//获得最大左子数组 right_sum = FIND_MAXIMUM_SUBARRAY(a, mid+1, high);//获得最大右子数组 cross_sum = FIND_MAX_CROSSING_SUBARRAY(a, low, mid, high);//获得最大中子数组 //最大左子数组为最大子数组 if(left_sum >= right_sum && left_sum >= cross_sum) { return left_sum; } //最大右子数组为最大子数组 else if(right_sum >= left_sum && right_sum >= cross_sum) { return right_sum; } //最大中子数组为最大子数组 else return cross_sum; } }
本次测试经过使用白盒测试的条件组合覆盖进行测试,执行足够的测试用例,使得每一个断定中条件的各类可能组合都至少出现一次ios
int FIND_MAXIMUM_SUBARRAY(int a[], int low, int high)
流程图经过流程图知,条件组合覆盖一共有4条路径,分别是ae,abf,abcg,abcd,按照条件组合的定义,共有14种可能的组合,分别是:git
1) low == highgithub
2) low != high算法
3) left_sum >= right_sum,left_sum >= cross_sum数组
4) left_sum >= right_sum,left_sum < cross_sum框架
5) left_sum < right_sum,left_sum >= cross_sum函数
6) left_sum < right_sum,left_sum < cross_sum工具
7) right_sum >= left_sum,right_sum >= cross_sum单元测试
8) right_sum >= left_sum,right_sum < cross_sum
9) right_sum < left_sum,right_sum >= cross_sum
10)right_sum < left_sum,right_sum < cross_sum
11)cross_sum >= left_sum,cross_sum >= right_sum
12)cross_sum >= left_sum,cross_sum < right_sum
13) cross_sum < left_sum,cross_sum >= right_sum
14)cross_sum < left_sum,cross_sum < right_sum
这里设置7个测试用例,用以覆盖上述14种条件组合,以下表所示:
测试用例 | 数组 | 期待值 | 覆盖组合号 | 执行路径 |
---|---|---|---|---|
测试用例1 | 1 | 1 | 1 | ae |
测试用例2 | 5, -3, 2, -3, 1 | 5 | 2,3,10,13 | abf |
测试用例3 | -2, 11, -4, 13, -5, -2 | 20 | 2,6,8,11 | abcg |
测试用例4 | 3, -4, -3, -7, 5 | 5 | 2,5,7,14 | abcd |
测试用例5 | -3, 2, 3, -2, 1 | 5 | 2,4,10,11 | abcg |
测试用例6 | -3, -2, 3, -4, 9 | 9 | 2,3,9,12 | abcg |
测试用例7 | 5,-4,-2,-3,1 | 5 | 2,3,9,14 | abcd |
//测试模块 TEST(max_arrayTest0, max_arrayCase0) { int a[0]; a[0] = 1; ASSERT_EQ(1, FIND_MAXIMUM_SUBARRAY(a, 0, 1)); } TEST(max_arrayTest1, max_arrayCase1) { int b[5] = {5, -3, 2, -3, 1}; ASSERT_EQ(5, FIND_MAXIMUM_SUBARRAY(b, 0, 4)); } //题目中的 TEST(max_arrayTest2, max_arrayCase2) { int c[6] = {-2, 11, -4, 13, -5, -2}; ASSERT_EQ(20, FIND_MAXIMUM_SUBARRAY(c, 0, 5)); } TEST(max_arrayTest3, max_arrayCase3) { int d[5] = {3, -4, -3, -1, 10}; ASSERT_EQ(10, FIND_MAXIMUM_SUBARRAY(d, 0, 4)); } TEST(max_arrayTest4, max_arrayCase4) { int e[5] = {-3, 2, 3, -2, 1}; ASSERT_EQ(5, FIND_MAXIMUM_SUBARRAY(e, 0, 4)); } TEST(max_arrayTest5, max_arrayCase5) { int f[5] = {-3, -2, 3, -4, 9}; ASSERT_EQ(9, FIND_MAXIMUM_SUBARRAY(f, 0, 4)); } TEST(max_arrayTest6, max_arrayCase6) { int f[5] = {5, -4, -2, -3, 1}; ASSERT_EQ(5, FIND_MAXIMUM_SUBARRAY(f, 0, 4)); } int main(int argc, char* argv[]) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
在终端依次输入:
g++ -o max_array.o -c max_array.cpp -I./include
g++ -o test *.o -I./include -L./lib -lgtest -lpthread
./test
全绿,测试经过!
刚开始测试时误解了条件组合覆盖的定义,一直纠结于怎么去对递归进行测试,后来才明白条件组合覆盖是要求使得每一个断定中的条件的各类可能组合至少出现一次,这样一来,直接对断定式进行测试就OK,所以,理解什么是单元测试很重要,并非说什么代码都须要去测试,那样只会徒劳