問題: 給定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,所以,理解什麼是單元測試很重要,並非說什麼代碼都須要去測試,那樣只會徒勞