Lab 2实验报告
Lab 2实验报告
实验目标概述
本次实验训练抽象数据类型(ADT)的设计、规约、测试,并使用面向对象 编程(OOP)技术实现 ADT。具体来说:
针对给定的应用问题,从问题描述中识别所需的 ADT;
设计 ADT 规约(pre-condition、post-condition)并评估规约的质量;
根据 ADT 的规约设计测试用例;
ADT 的泛型化;
根据规约设计 ADT 的多种不同的实现;
针对每种实现,设计其表示 (representation)、表示不变性(rep invariant)、抽象过程(abstraction function) 使用 OOP 实现 ADT,并判定表示不变性是否违反、各实现是否存在表 示外泄(rep exposure);
测试 ADT 的实现并评估测试的覆盖度;
使用 ADT 及其实现,为应用问题开发程序;
在测试代码中,能够写出 testing strategy 并据此设计测试用例
实验环境配置
简要陈述你配置本次实验所需环境的过程,必要时可以给出屏幕截图。
特别是要记录配置过程中遇到的问题和困难,以及如何解决的。
在这里给出你的GitHub Lab2仓库的URL地址(Lab2-学号)。
https://github.com/ComputerScienceHIT/Lab2-1170300623.git
实验过程
请仔细对照实验手册,针对三个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
Poetic Walks
在这里简要概述你对该任务的理解。
这个问题集的目的是实践设计、测试和实现抽象数据类型。此问题集侧重于实现向您提供规范的可变类型;下一个问题集将侧重于必须选择规范的不可变类型。
Get the code and prepare Git repository
从GitHub获取该任务的代码、在本地创建git仓库、使用git管理本地开发。
Problem 1: Test Graph
以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。
我们只测试(然后实现)带有 String 顶点标签的图。之后,我们将扩展到其他类型的标签。
为了适应 在 接口的 多个实现 上运行我们的测试 Graph ,下面是设置:
用静态 方法 在测试策略和测试 。由于该方法是静态的,因此只会有一个实现,我们只需要运行一次这些测试。我们提供了这些测试。您可以自由更改或添加它们,但您可以将它们保留原样用于此问题。为你的所有 实例 方法 编写测试策略和测试。
与 GraphStaticTest 我们编写的任何其他JUnit测试类一样, GraphInstanceTest 它不同,因为不能直接运行它。它有一个空白的等待填充: emptyInstance() 将提供空 Graph 对象的 方法 。在接下来的问题中,我们将看到两个 子类 的 通过返回不同类型的空图的空白填补。 GraphInstanceTest 必须是 Graph 规范的合法客户 。任何针对你的实现的测试都会在下一个问题的子类中出现。
Problem 2: Implement Graph
以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。
Implement ConcreteEdgesGraph
抽象函数:将图中的所有边表示为一对连接的顶点,带有源的目标方向,带有重量。表示不变式:顶点是一组类型为L的对象,边缘是由不同的加权边缘构成的列表,不同的顶点对(顶点不存在多于一次)。
一个边必须连接到至少v个顶点,例如,2条边至少需要3个顶点,5条边需要至少4个顶点vertices.size()> = Math.ceil(Math.sqrt(2 * edges.size)+ 0.5),顶点和边是可变类型,所以操作使用防御性副本和不可变的包装,以避免将代表对象分享给客户端。
有一段辅助代码:检查图中是否存在边,不存在返回-1
Implement ConcreteVerticesGraph
将一个可变类型存储到列表中,所以这样的方法as contains()和get()不能用于访问顶点。这是一个要求,我们不添加新的领域,我试图在不违反条件的情况下使用查找表,会将顶点的标签存储在与位置匹配的列表中,他们的相对顶点有恒定的时间访问,如果允许改变代表,我会使用地图:地图<字符串,顶点>,任何顶点不会影响。
抽象函数:将一个有向加权图表示为多个顶点,作为源连接到目标对,每对具有一个重量。
还有一个辅助方法
测试结果
Problem 3: Implement generic Graph
Make the implementations generic
将具体类的声明更改为:
public class ConcreteEdgesGraph implements Graph { … }
class Edge { … }
和:
public class ConcreteVerticesGraph implements Graph { … }
class Vertex { … }
更新两个实现以支持任何类型的顶点标签,L而不是使用占位符String。粗略地说,找到并替换 String 代码中的 所有实例 L !这种重将 ConcreteEdgesGraph , ConcreteVerticesGraph , Edge ,和 Vertex 泛型类型。Edge 或者 类型声明了变量List将需要成为 Edge和List<Edge> 。同样, new ConcreteEdgesGraph() 或者 构造函数 new Edge(),这些将需要成为 new ConcreteEdgesGraph() 和 new Edge()。
Problem 4: Poetic walks
Test GraphPoet
自由添加其他方法 GraphPoet ,但不能更改所需方法的签名。可以自由地加强所需方法的规格,但不能削弱它们。请注意,这可能意味着测试对于 GraphPoet 其他人的实现无法使用,因为已加强或添加到规范。测试应该使用一个或多个样本语料库文件。将这些文件放在 test/poet 目录中 - 与目录相同 GraphPoetTest.java 。在代码中引用它们。虽然仍然必须测试和实施 GraphPoet(File) ,但可以添加操作 GraphPoet 。 String 举例来说,添加一个创建者 可能会简化测试 poem(…) ,但需要以新创建者的额外测试为代价。
但是吧,测试失败。。。
Implement GraphPoet
必须在GraphPoet的代表中使用Graph。 GraphPoet应该仅依赖于Graph的规格,而不依赖于特定Graph实现的细节。 GraphPoet的实现完全取决于自己。要阅读语料库文件,至少要考虑三个Java API:
FileReader是从文件读取的标准类。 在BufferedReader中包装FileReader使您可以使用方便的readLine()方法一次读取整行。
实用函数Files.readAllLines(…)将读取Path中的所有行。 我们的诗人需要一个文件,但是文件提供了一个toPath()方法来获得一个Path。
Class Scanner旨在将输入文本分解为多个部分。 它提供了许多功能,您需要仔细阅读其规格。
Graph poetry slam
如果想要,用一个很酷的例子来更新Main.java中的main(…)方法:从最小输入中得到一首有趣的诗,给出语料和输入的令人惊讶的诗,或者其他很酷的东西。
Before you’re done
Github desktop上传代码
Re-implement the Social Network in Lab1
主要目标是构造一个图的结构描述人与人之间的关系。
FriendshipGraph类
FriendshipGraph描述出这个关系图,经过分析,人际关系图应该是一个稀疏图,所以选择邻接表来实现。为每个成员创建一个List来存放他的朋友图有两个要素,点和边,所以要实现addVertex和addEdge两个函数。
Person类