最大子数组求和并进行条件组合覆盖测试

简介

  • 算法导论第四章介绍过使用分治法求最大子数组问题,其基本思想就是把一个数组分成三部分,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,来查看具体如何实现,这里主要给大家展示功能函数模块和测试该函数模块

二.功能函数模块

//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;

    }
}

三.测试

本次测试通过使用白盒测试的条件组合覆盖进行测试,执行足够的测试用例,使得每个判定中条件的各种可能组合都至少出现一次

1.功能函数int FIND_MAXIMUM_SUBARRAY(int a[], int low, int high)流程图

通过流程图知,条件组合覆盖一共有4条路径,分别是ae,abf,abcg,abcd,按照条件组合的定义,共有14种可能的组合,分别是:

1) low == high

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,因此,理解什么是单元测试很重要,并不是说什么代码都需要去测试,那样只会徒劳

原文地址:https://www.cnblogs.com/Stone-Blossom/p/8667060.html

时间: 2024-10-12 18:50:10

最大子数组求和并进行条件组合覆盖测试的相关文章

环状二维数组最大子数组求和

题目:返回一个二维整数数组中最大子数组的和.要求:输入一个二维整形数组,数组里有正数也有负数.二维数组首尾相接,象个一条首尾相接带子一样. n数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为O(n). 结对编程要求: 两人结对完成编程任务. 一人主要负责程序分析,代码编程. 一人负责代码复审和代码测试计划. 发表一篇博客文章讲述两人合作中的过程.体会以及如何解决冲突(附结对开发的工作照). 结对开发过程: 这次的编程开发是基于上次的以为数

首尾相连的二维数组最大子数组求和

题目:返回一个二维整数数组中最大子数组的和.要求:输入一个二维整形数组,数组里有正数也有负数.二维数组首尾相接,象个一条首尾相接带子一样. n数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为O(n). 结对编程要求: 两人结对完成编程任务. 一人主要负责程序分析,代码编程. 一人负责代码复审和代码测试计划. 发表一篇博客文章讲述两人合作中的过程.体会以及如何解决冲突(附结对开发的工作照). 结对开发过程: 这次的编程开发是基于上次的以为数

最大子数组求和问题

一.题目与要求 题目: 返回一个整数数组中最大子数组的和 要求: 1.输入一个整形数组,数组里有正数也有负数. 2.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.       3.求所有子数组的和的最大值.要求时间复杂度为O(n). 结对编程要求:        1.两人结对完成编程任务.       2.一人主要负责程序分析,代码编程.       3.一人负责代码复审和代码测试计划.       4.发表一篇博客文章讲述两人合作中的过程.体会以及如何解决冲突(附结对开发的工

软件工程结对开发——一维最大子数组求和溢出问题

一.题目要求 题目:返回一个整数数组中最大子数组的和. 要求: 要求程序必须能处理1000 个元素: 每个元素是int32 类型的: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 二.设计思路 将数组第一个和第二个数置为2的63次方,观察结果是否溢出. 三.源代码 1 package com.java.lianxi; 2 3 import java.util.Scanner; 4

eclipse的安装及最大子数组求和

我安装的是eclipse.由于eclipse是一个基于Java的课扩展开发平台,所以在安装eclipse之前要先安装Java的开发工具JDK(Java Devolopment Dit),且安装JDK需要配置环境变量. 首先要下载JDK.下载JDK是为了安全起见,尽量在Oracle官网下载,官网地址是:http://www.oracle.com/    下载时需要用户登录,可以免费注册然后就能下载了. 打开官网后会看到如下界面,首先将光标放到Downloads的位置,在其显示的页面找到 Java

二维数组中最大子数组的和

题目:返回一个二维整数数组中最大子数组的和. 要求: 输入一个二维整形数组,数组里有正数也有负数. 二维数组中连续的一个子矩阵组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 思路: 借鉴网上代码整理得思路: 根据一位数组最大子数组求和的编程思路,讲二维数组转化成一维数组求解: 即求出每一行的最大子数组之和,通过比较各行最大子数组之和的大小,求出只有二维数组只有一行的情况下的最大子数组之和: 然后求每两行最大子数组之和,即将每两行的相同列相加,将二维数

循环数组,求和最大子数组

题目: 返回一个整数数组中最大子数组的和. 要求: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大. 同时返回最大子数组的位置. 求所有子数组的和的最大值.要求时间复杂度为O(n). 思路: 1. a.定义长度为n的一维数组,实际随机生成的时候生成长度为2n的数组,即n+1~2n是对1~n的重复 b.利用长度为n时的求法

求最大子数组02

题目:整数数组中最大子数组的和 要求: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 如果数组A[0]……A[j-1]首尾相邻,允许A[i-1],…… A[n-1],A[0]……A[j-1]之和最大. 同时返回最大子数组的位置. 求所有子数组的和的最大值. 这次任务多了一个要求就是这个数组是环形的, 也就是可以从A[i-1],…… A[n-1],A[0],A[1]这样的数组也阔以,那么首先想到的就是循环链表,然后控制求和的子数组长度即

结对开发Ⅵ——循环二维数组求和最大的子数组

一.题目及要求 题目:返回一个二维整数数组中最大子数组的和. 要求: 输入一个二维整形数组,数组里有正数也有负数.    二维数组首尾相接,象个一条首尾相接带子一样.     数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.  求所有子数组的和的最大值.要求时间复杂度为O(n). 二.设计思路 (1)二维数组我们采用的还是数组的形式: (2)读取nxm的二维数组,储存成nx2m,把前m列重复加在二维数组的最后: (3)搜索最大数组的方法和不循环的二维数组是一样的,就是再加上判断条