软件构造Lab1心得

在实验过程中,了解到了java不同层面的许多知识,也遇到了许多问题,在这里分享这些经验和实验心得。

任务1 - 幻方

文件读写

了解到文件读写的方法主要有三种:

1. FileInputStream和FileOutputStream

FileInputStream用于从文件读取数据,可以用关键字new来创建。

构造方法有很多,一种是利用字符串类型的文件路径来创建:

InputStream s = new FileInputStream("C:/java/helloworld");

另外还可以利用文件对象来创建:

File f = new File("C:/java/helloworld"); InputStream in = new FileInputStream(f);

FileOutputStream用于向文件中写数据。 如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。

有两个构造方法可以用来创建 FileOutputStream 对象。

使用字符串类型的文件名来创建一个输出流对象:
OutputStream f = new FileOutputStream("C:/java/hello")
也可以使用一个文件对象来创建一个输出流来写文件。我们首先得使用File()方法来创建一个文件对象:
File f = new File("C:/java/hello"); OutputStream fOut = new FileOutputStream(f);

2. BufferedWriter和BufferedReader

BufferedWriter 和BufferedRead是缓冲字节流,属于高级流,按行读取字符串。

由于这两个字符流不能直接处理字节流,所以需要InputStreamReader和OutputStreamWriter这两个转换流做纽带,

将低级字节流和BufferedReader、BufferedWriter关联起来。范例:
image

判断矩阵是否是magic

在做这部分内容时,观察到有很多同学都是对列进行判断,对行进行判断,对斜角线进行判断

这里可以利用一个双层的for循环完成判定

点击查看代码
 //  判断是否是一个magic square
        int sum = 0;
        int colsum = 0;
        int rowsum = 0;
        int slashsum1 = 0;
        int slashsum2 = 0;
        for (int i = 0; i < row; i++) {
            //  求取基准值
            sum += matrix[0][i];
        }
        for (int i = 0; i < row; i++) {
            //  分别对两斜线、行、列数据求和
            colsum = 0;
            rowsum = 0;
            slashsum1 += matrix[i][i];
            slashsum2 += matrix[i][row - i - 1];
            for (int j = 0; j < col; j++) {
                rowsum += matrix[i][j];
                colsum += matrix[j][i];
            }
            if (sum != rowsum || sum != colsum) {
                System.out.println("Not a Magic Square!");
                return false;
            }
        }
        if (sum != slashsum1 || sum != slashsum2 || sum != rowsum || sum != colsum) {
            System.out.println("Not a Magic Square!");
            return false;
        }
        else return true;

任务2 - 海龟画图

凸包问题

凸包(Convex Hull)是一个计算几何(图形学)中的概念。

在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。X的凸包可以用X内所有点(X1,...Xn)的凸组合来构造.

在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。

用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。

凸包算法

Graham扫描法

思路:先找到凸包上一个点,从该点开始逆时针方向逐个寻找凸包上的点。

步骤:

  1. 把所有点放在二维坐标系中,则纵坐标最小的点一定是凸包上的点,设为P0

  2. 把所有点的坐标平移,使得P0成为新的原点

  3. 计算各个点相对于P0的角度,将它们按角度从小到大的顺序对各个点排序。当角度相同时,距离P0近的点排序放在前面。由几何知识我们可以知道,排序后的点中,第一个点P1和最后一个点Pn肯定是凸包上的点,否则的话,这两点始终在P0和其它任意点的连线的外侧。

  4. 以上是求取凸包的准备步骤,我们知道了凸包上的两个点P0,P1,我们将它俩放在栈中,接着我们从排序中的第二个点P2出发,开始找凸包上的第三个点。

  5. 连接P0和栈顶的点,得到直线L。看当前点是在直线L的右边还是左边。如果在直线的右边就执行步骤6,在直线上或左边就执行步骤7。

  6. 如果在右边,则栈顶的点不是凸包上的点,把栈顶元素出栈,执行步骤5。

  7. 当前点是凸包上的点,压入栈。执行步骤8。

  8. 检查当前点是不是排序的得到的点中最后一个点,是则结束,不是则当前点为下一个点,执行步骤5。

算法代码:略

任务3 - 社交图

getDistance函数

函数要求,给出两个参数Person a, Person b,求出两个人的社交距离。

分析来看,该问题就是图中两点的最短路径问题

我们采取比较经典的Dijkstra算法来解决问题。

对于计算机专业的人来说,对该算法的了解是最基本的。

这里作简要介绍:

数据结构(rep)用到了队列Queue,具体实现是LinkedList,和列表List,具体实现是ArrayList,和Map,具体实现是HashMap。

  1. 初始化:我们将Person a放入队列中,并将基础distance值0,二者一起键入HashMap。

  2. 判断栈空不空,空则执行步骤3,不空则执行步骤4。

  3. 退出循环,返回-1。

  4. 弹出队列头元素,判断是否与Person b相同,并将该元素放入ArrayList中,标记为已访问,相同则执行5,不同则执行6。

  5. 返回HashMap中该Person的对应distance值。

  6. 不同,则对从队列弹出的Person的朋友们,其中符合不在队列中(因为求最短路径,该路径一定比已经在队列中的大)而且没有访问过的元素的条件,将符合条件的朋友压入队列。执行步骤2。

最终返回值就是Person a, Person b的社交距离了。

实现代码:

点击查看代码
public int getDistance(Person a,Person b) {	
		//	利用队列进行广度优先搜索
		Queue<Person> friendqueue = new LinkedList<Person>();
		ArrayList<Person> visitedPerson = new ArrayList<Person>();
		HashMap<Person, Integer> distanceMap = new HashMap<Person,Integer>();
		friendqueue.add(a);
		int distance = 0;		//	用于计算两点间最短距离
		distanceMap.put(a, distance);		//	a距离自身的距离是0
		while (!friendqueue.isEmpty()) {
			Person find = friendqueue.poll();
			visitedPerson.add(find);		//	从栈中取出后,访问完毕后不再访问
			if (find == b) {		//	如果等于b,返回距离
				return distanceMap.get(find);
			}
			else {
				for (Person p : find.list) {		//	每次向栈中添加成员后,同时向hashmap中键入person以及对应distance
					if ((!friendqueue.contains(p)) && (!visitedPerson.contains(p))) {
						friendqueue.add(p);		
						distanceMap.put(p, distanceMap.get(find)+1);
					}
				}
			}
		}
		return -1;
	}

总之,软件构造实验并不太难,而是突然面对陌生的编程语言难以接受,学会适应,你会发现,语言之间也是可以相通的。

对于实验,只要细心研究,会有所收获的。

posted @ 2022-05-22 16:35  大专菜码  阅读(43)  评论(0)    收藏  举报