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

问题:

返回一个二维整数数组中最大联通子数组的和思路:把数按行分成几个一维数组,对于该一维数组,求出他们的最大连续数组之和,并且记录下最大连续数组的第一位和最后一位的位置,之后判断几个一维数组的最大连续数组的位置是否相接或包括(如,第一行是1和4,第二行是3和5,这样就相连)。最后在加上没有包括的正数(必须在上一行的最大连续数组的第一位和最后一位的位置之间)。输出之前之和就行。

 

一、实验目的

1、以指定格式的文本文件形式输入数组。

2、数组由一维变为二维。

3、给出单元测试/代码覆盖率的最终覆盖率的报告,撰写博客。

二、实现代码

package test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class MaxIntArray {
    public static void main(String[] args) throws IOException {

        Integer[][] c=new Integer[100][];

        c=ReadFile("C:\\Users\\Administrator\\Desktop\\arr.txt");
        for(int i=0;i<c.length;i++){
            for(int j=0;j<c[0].length;j++){
                System.out.print(c[i][j]+" ");
            }
                System.out.println();
        }
//        System.out.print(c[2][2]);
        System.out.println("1:"+GetMaxSUM(c));
//        System.out.println("2"+MaxSUM(c));
    }
    public static Integer[][] ReadFile(String str){
        FileReader file = null;

        try {
            file = new FileReader(str);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("文件测试数据如下:");
        BufferedReader br = new BufferedReader(file);//读取文件
        try {
            String line = br.readLine();//读取一行数据
            int lenx = Integer.parseInt(line);
            line = br.readLine();//读取一行数据
            int leny = Integer.parseInt(line);
//            System.out.println(lines);

            String []sp = null;
            String [][]c = new String[lenx][leny];
            Integer[][] cc = new Integer[lenx][leny];
            int count=0;
            while((line=br.readLine())!=null) {//按行读取
                sp = line.split(" ");//按空格进行分割
//                System.out.println("Length:"+sp.length);
//                System.out.println("sp:"+sp[0]);
                for(int i=0;i<sp.length;i++){
                    c[count][i] = sp[i];
                }
                count++;
            }
            for(int i=0;i<lenx;i++){
                for(int j=0;j<leny;j++){
                    cc[i][j] = Integer.parseInt(c[i][j]);
//                    System.out.print(cc[i][j]+" ");
                }
//                System.out.println();
            }
            return cc;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
   
    public static int GetMaxSUM(Integer[][] a){
        int n=a.length;
        int m=a[0].length;
        //分块
        Integer[] Max=new Integer[100];
        Integer[] Begin=new Integer[100];
        Integer[] End=new Integer[100];
        Integer[] b=new Integer[100];
        for(int i=0;i<n;i++)
        {
            //按行分组
            for(int j=0;j<m;j++)
            {
                b[j]=a[i][j];

            }
            MaxIntArray(b,Max,Begin,End,m,i);
        }

        int max=Max[0];
        for(int i=0;i<n-1;i++)
        {
            if((Begin[i]<=End[i+1]&&Begin[i]>=Begin[i+1])||(End[i]<=End[i+1]&&End[i]>=Begin[i+1]))
            {
                max=Max[i+1]+max;
            }
            else
            {
                //如果不能直接连通,判断代价是否合适
                if(Begin[i]>End[i+1])
                {
                    int t = Begin[i]-End[i+1];
                    int s = Begin[i];
                    int temp=0;
                    for(int k=0;k<t;k++)
                    {
                        temp+=a[i+1][s-k];
                    }
                    if(temp+Max[i+1]>0)
                        max=temp+Max[i+1];
                }
                if(End[i]<Begin[i+1])
                {
                    int t = Begin[i+1]-End[i];
                    int s = End[i];
                    int temp=0;
                    for(int k=0;k<t;k++)
                    {
                        temp+=a[i+1][s+k];
                    }
                    if(temp+Max[i+1]>0)
                        max=temp+Max[i+1];
                }
            }
        }
        return max;
    }
    public static void MaxIntArray(Integer[] a,Integer[] max,Integer[] begin,Integer[] end,int n,int index){

        Integer[] Max=new Integer[100];
        Max[0] = 0;
        int i = 0;//数组下标
        int j = 0;//最大值数组下标
        int temp=0;//中间变量
        //记录子数组的起始位置和末位
//        Integer[] Bg=new Integer[100];
        Integer[] Bg={-1,-1,-1,-1,-1};
        Integer[] Ed=new Integer[100];
        while(i<n){
            if(temp+a[i]>=Max[j])
            {
                temp=temp+a[i];
                Max[j]=temp;
                if(Bg[j]==-1)
                    Bg[j]=i;
                Ed[j]=i;
                i++;
            }
            else if(temp+a[i]<Max[j]&&temp+a[i]>0)
            {
                temp=temp+a[i];
                i++;
            }
            else if(temp+a[i]<=0)
            {
                i++;
                j++;
                Max[j]=0;
                temp=0;
            }

        }
        max[index] = Max[0];
        int q=0;
        for(int k=0;k<=j;k++){
            if(Max[k]>max[index])
            {
                max[index]=Max[k];
                q=k;
            }
        }
        begin[index]=Bg[q];
        end[index]=Ed[q];
    }
}

三、单元测试

3.1 测试环境搭建

完成项目的创建后,点击 文件File-点击新建,选择Junit Test Case,创建MaxIntArrayTest.java测试类图片如3-1所示:

 

图3-1创建测试类

 

 3.2 创建测试用例

因为二维数组是从TXT文件中进行输入的,所以首先应该创建用于数据读取的TXT文件,我一共创建了五组测试用例,测试用例如下表3-2:

表3-2测试用例

arr.txt

3
4
5 1 2 3
1 2 3 4
1 2 4 5

arr1.txt

3
3
1 5 2
5 4 9
6 2 3

arr2.txt

2
3
2 3 4
5 9 8

arr3.txt

3
2
2 3
5 1
6 4

arr4.txt

5
4
1 1 2 3
2 2 3 1
3 3 1 2
4 4 5 6
1 2 3 4

注意:在TXT文件中写入二维数组的时候要先写行,回车在写列,最后写二维数组,并且不能有空格。

3.3创建测试代码

然后,在MaxIntArrayTest.java测试类里面编写测试的代码,并得到运行结果。

代码:

package test;

import static org.junit.Assert.*;
import static test.MaxIntArray.GetMaxSUM;
import static test.MaxIntArray.ReadFile;
import org.junit.Test;

public class MaxIntArrayTest {

    @Test
    public void test1() {
        String str="C:\\Users\\ASUS\\Desktop\\arr.txt";
        Integer[][] c=ReadFile(str);
        System.out.println("MaxSUM:"+GetMaxSUM(c));
    }
    
    @Test
    public void test2() {
        String str="C:\\Users\\ASUS\\Desktop\\arr1.txt";
        Integer[][] c=ReadFile(str);
        System.out.println("MaxSUM:"+GetMaxSUM(c));
    }
    
    @Test
    public void test3() {
        String str="C:\\Users\\ASUS\\Desktop\\arr2.txt";
        Integer[][] c=ReadFile(str);
        System.out.println("MaxSUM:"+GetMaxSUM(c));
    }
    
    @Test
    public void test4() {
        String str="C:\\Users\\ASUS\\Desktop\\arr3.txt";
        Integer[][] c=ReadFile(str);
        System.out.println("MaxSUM:"+GetMaxSUM(c));
    }
    
    @Test
    public void test5() {
        String str="C:\\Users\\ASUS\\Desktop\\arr4.txt";
        Integer[][] c=ReadFile(str);
        System.out.println("MaxSUM:"+GetMaxSUM(c));
    }
    

}

测试结果:

       

 

 

由上图可知,五组数据都通过了测试。

 四、代码覆盖率

 4.1Jacoco插件安装

在Eclipse下依次点击 Help->Eclipse Marketplace->搜索EclEmma,图片如下:

 

 

 接下来按步骤安装即可。
安装成功后,在Window->Show View->Other中找到Coveage可以打开界面

4.2 覆盖率检测

选择想要测试的单元测试文件或者文件夹,编写成功后右键项目选择Coverage As -> JUnit Test,
执行后效果如图:

对程序代码进行代码覆盖率检测,如下图所示

 

 

 

 对单元测试代码进行代码覆盖率检测,如下图所示:

 

 

 注意:绿色区域:代码被执行过;黄色区域:代码部分被执行过;红色区域:代码没有被执行过。

覆盖率测试成功后会出现代码覆盖率的统计信息,如下图所示:

 

 

由此图我们 可以看到:每个方法中执行到的代码和未执行的代码,可以看到代码测试覆盖率。看代码,是取得随机数,if判断可能出现不满足,可能满足的情况, 需要多次执行该代码,得到多次的代码覆盖率,然后吧多次得到的覆盖率合并,得到这个类总的代码测试覆盖率。

五、小结

1、通过Eclipse插件可以快速验证测试用例的代码覆盖率,在大型项目中,合格的测试用例覆盖率能够很好的减少因临时修改代码而导致的重大BUG,但不建议盲目追求代码覆盖率,尤其是中小型项目。

如果要测试整个项目中代码的测试覆盖率,可能比较麻烦,至少需要吧所有代码的测试类执行一遍,并且把所有代码执行的路径都考虑到才准确。
2、别忘记测试异常情况,空指针,或者其他异常后,执行异常代码,也会增加代码测试覆盖率的。
3、如果得到代码测试覆盖率比较高,显而易见能看出代码安全性会比较能保证。

六、参考资料:

单元测试:https://blog.csdn.net/weixin_40814407/article/details/86575946

覆盖率:https://blog.csdn.net/qq_39312230/article/details/83269189

以上就是本次实验的全部代码以及分析,欢迎大家讨论!

posted @ 2021-03-29 20:36  暗夜深林  阅读(165)  评论(1)    收藏  举报