软件构造实验一

前言:第一次实验主要是想帮助我们掌握java基础知识,因此deadline相对宽松一些,断断续续把它写完了,今天在这里给总结一下

P1

在P1的实验指导中已经给出了提示:从文件中逐行读取字符串,然后将字符串根据split方法以“\t”进行划分,将每一个元素转化为整数进行加和,验证其是否为幻方矩阵。
我总结了实验中遇到的几个关键点:
①读取文件
②字符串分割、转化时的格式问题:不符合标准方阵格式该怎样处理
③保存元素和时用静态还是动态数组保存,需要几个数组来存储

` ①读取文件
java读取文件有很多方法,我这里选了自己觉得还算是比较简洁的,打算作为以后自己读取文件的代码模板:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

②异常处理

选择在字符串转化为整数时用try-catch捕获异常,打印提示
在这里插入图片描述
这样可以处理分割时不足“\t”以及有元素为浮点数的情况
其次,设置一个excflag变量,标志是否出现非正整数以及行列数不相等情况
在这里插入图片描述
在这里插入图片描述

③保存元素和

这里我先计算矩阵第一行的元素个数,以此作为数组的大小,循环过程中检查是否出现了行列数不等的情况,防止数组越界
在这里插入图片描述另外还有一个产生幻方矩阵的函数,该函数对于一个奇数输入n,可以产生n*n的幻方矩阵,实验要求我们对其进行分析和验证。
代码复制如下:

public static boolean generateMagicSquare(intn) {
intmagic[][] = newint[n][n];
introw = 0, col = n / 2, i, j, square = n * n;
for(i = 1; i <= square; i++) { 
	magic[row][col] = i;
	if(i % n == 0)
		row++;
	else{
		if(row == 0)
			row = n -1;
		else
			row--;
		if(col == (n -1))
			col = 0;
		else
			col++;}
		}
	for (i = 0; i < n; i++) {
		for (j = 0; j < n;j++)
		System.out.print(magic[i][j]+"\t");
		System.out.println();}return true;
	}
	return true;
}

对其分析如下:
①初始位置选择第0行的正中间,将1置于此,下一个整数从最后一行开始
②沿着左下至右上的对角线方向放置连续整数,行数递减,列数递增
③行数递减至第0行时,再置为最后一行继续循环
④列数递增至n-1列时,置为第0列继续循环
⑤当下一个应放置位置已有整数或者到达矩阵的右上顶点时,选择其下一行的正下方位置作为代替(用i%n==0来判断)
对其他输入产生异常的原因如下:①n为偶数时矩阵左下角的元素会出现越界现象,因此出现异常②n为负数时创建二维数组时便会出现异常,矩阵的大小不能是负数

P2

这个任务里前面几个函数比较基础,这里不准备做介绍,感兴趣的可以查看MIT网站:
http://web.mit.edu/6.031/www/fa18/psets/ps0/
个人感觉比较有意思也是比较有思考价值的是关于构造凸包的函数。通俗地讲,构建凸包是指,给定一个平面内的点的集合,寻找一个最小集合,使其中的点可以形成包围所有点的凸多边形。
我对这个问题的理解如下:如果能找到一个凸包上的点,由于凸包要将所有点包围在内,因此如果利用已知点找到一个点:使得所有点都在该点与已知点的连线的一侧(无论左、右),则这一点必为凸包上点,如果其余点都位于连线一侧,说明从已知的凸包上点到该点所需的转向角最小,因此只需遍历点集,找到转向角最小的点即可。如图所示:
在这里插入图片描述
这里先把需要用到的之前设计的函数介绍一下:calculateBearingToPoint。给定当前点位置坐标以及目标点坐标,以及目前朝向的角度,计算由当前点需要转过多少角度来朝向目标点。我这里主要利用Math库中的atan函数,根据正切值计算角度值,我这里根据当前点与目标点之间的位置关系划分九个维度:重合、左上、左、左下、下、右下、右、右上、上
若A点为已知凸包上点,找到这样一个点B:使得其余所有点都位于两点连线AB的同一侧,则B也为凸包上点。
①因此需要找到第一个凸包上点,我的方法是遍历点集,找到离原点最远的一个点,这个点就是凸包上的点,是凸包的一个“角”
在这里插入图片描述
②寻找下一个凸包上点时计算两个坐标点之间旋转所需转向角,点集中转向角最小的一个便是新的凸包上点,初始转向角置为0,直到又回到第一个凸包上点循环终止
在这里插入图片描述
③有一种特殊情况:三点共线,那么两两之间的转向角都是0,一定会在循环中加入凸包中,但是凸包是最小点集,简单分析便可知道这种情况中间点一定是多余的,因此代码中要有对这一部分的判断、删除
在这里插入图片描述
然后来介绍一下drawPersonalart,这是自由发挥的范畴,我用了多个循环以及控制转向角来画了多圆组合图形
在这里插入图片描述

P3

这个问题的实质便是图问题,其中关键是求最小距离的算法,这一问题是需要解决的关键问题,其他都是一些基础的图操作:如添加顶点,添加边等等。
这里本来是想用动态二维数组来使用邻接表表示的,但觉得这样getDistance算法实现起来会很麻烦,因此还是使用了10000*10000的邻接矩阵。
当初本来是想用上学期数据结构课中学习的Dijkstra算法来计算最短路径,但看到实验指导上提到广度/深度优先两大搜索方法,便,想用图的搜索来计算最短路径。
我的总体思路是广度优先搜索求最短距离,具体思路如下:
①判断两个顶点是否在顶点集中,不在则打印提示并返回-1
②判断是否为同一顶点,若是,省去遍历操作,直接返回0
③关键部分:利用一般的广度优先搜索进行遍历,这里用List类创建一个数组作为队列来使用。
大体上与一般的广度优先搜索没什么不同,但困扰我的一点是如何保证这距离是最短的。一个顶点可能与多个顶点相连,这多个顶点只有全部遍历完成以后并且没有找到目标点时目前的距离才能进行加1操作,我把这多个顶点称作位于“同一级”,即同级元素遍历完全后距离才能加1.那么同级元素就需要额外的空间进行存储,并且随着遍历的进行,顶点在变,顶点的朋友也在变,因此同级元素也在变,因此当与一个顶点相关联的顶点遍历完成时这个同级元素需要及时更换。

因此我在这里的实现方法是新建两个列表:nowList和friendListnowList中存储的是与目前遍历的元素同级的元素,friendList中存储的是nowList中元素的所有朋友元素。这样每遍历一个同级元素后,就将其从nowList中移除,遍历时的朋友元素都已经加入到friendList中,当nowList为空时说明同级遍历完成,将friendList中元素全部复制给nowList,再将friendList置空,便实现了同级元素的变换。具体代码如下:
在这里插入图片描述
通过了实验指导中要求的样例以及自己设计的测试样例,觉得设计起来还挺有趣的。

总结:以上是我在实验过程中自己遇到的觉得比较有价值的点,今天在这里写个随笔总结起来,觉得以后学习时也可能还会有帮助。当然,我的理解不一定有多严谨,如有错误敬请指正!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值