最大子數組求和並進行條件組合覆蓋測試

簡介

  • 算法導論第四章介紹過使用分治法求最大子數組問題,其基本思想就是把一個數組分紅三部分,a[0:n/2],a[n/2+1:n],a[j:k] (其中0<=j<=n/2,n/2+1<=k<=n),經過遞歸分別求出他們的最大子數組和,而後再從中挑出最大的一個值,即爲該數組的最大子數組值,該算法的時間複雜度爲O(nlogn)
  • 白盒測試有語句覆蓋、斷定覆蓋、條件覆蓋、斷定/條件覆蓋、條件組合覆蓋這五個覆蓋標準
  • 環境:Ubuntu 16.04
  • 語言:C++
  • 測試工具:GTest(Gtest框架搭建教程)

一.問題

問題: 給定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

1.功能函數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

2.測試代碼

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

相關文章
相關標籤/搜索