Lab2图形结构及诗歌漫步的实现

Poetic Walks

这个任务总体分成了两大部分,其中第一部分是要我们自己用两种不同的方式设计一个图类,是带有标记顶点的可变加权有向图的抽象数据类型。首先我们需要根据提示先对测试用例进行设计,然后分别完成针对String的边实现和点实现,然后进一步将可以支持的类型拓展到泛型。实验这一部分完成之后还需要根据这个图形结构生成一个诗歌生成工具,添加一些满足条件的词语到语句中。

Test Graph

实验开始的首先任务就是针对需要实现的图形数据结构进行测试代码的设计,这样的设计原则也符合测试开发的原则。但是与最终所需要呈现的代码不同的是,最后我们需要实现的代码是针对泛型进行设计的,但是第一步的实现却是通过String来进行设计的。所以与之想匹配的就是先针对字符串数据进行测试用例的编写。设置完成之后先要完成原函数的代码编写才能进行测试。同时这一步还需要完成一个静态测试用例的编写。由于实验最后需要支持各种不同的类型,因此在这个函数的设计中,我们添加了两种数据类型,一种是Integer,另一种是Character。针对具体的实验结果需要先完成源代码的编写我们才能知道。

Implement Graph

Implement ConcreteEdgesGraph

这个部分需要我们根据边的类对图形结构的不同方法进行设计。首先我们需要先进行边类的设计。边类的设计相较于其他部分的设计来说是比较简单的,我们只需要保存对应的原点、终点和边上的权值即可。首先相关属性如下:

    private final String source;
    private final String target;
	private final int weight;

因此针对上面描述的表示不变性,我们设计checkRep函数进行检查。同时在边类中我们也设计了3个get函数获得边的属性。在这个方法的编写中我们还对toString函数进行了重写,为了能够更好地显示边的信息。其中的检查函数和打印函数如下:

    // TODO checkRep
	/**
	 * 检查边的表示
	 */
	private void checkRep() {
		assert this.source != null;
		assert this.target != null;
		assert this.weight > 0;
	}
	/**
	 * 打印这条边的信息
	 * @return String 包含边的原点终点权值的字符串信息
	 */
	@Override
	public String toString() {
		return "Edge:" + source.toString() + " to " + target.toString() + "," + "Weight:" + weight + "\n";
	}

上面我们对边的类进行了设计,为了更好地编写图形数据结构。然后根据边类的信息我们设计ConcreteEdgesGraph函数。这个函数中有两个属性是我们需要保存的,它们分别是:

    private final Set<String> vertices = new HashSet<>();
	private final List<Edge> edges = new ArrayList<>();

接下来就是对Graph接口中定义的各个不同的功能进行实现,具体的实现方法如下:
public boolean add(String vertex) 这个函数的实现较为简单,只需要判断这个顶点是否加入到了顶点集合中,如果这个顶点集合中已经包含了这个顶点,那么直接返回false,否则将其添加进入顶点集合中,同时进行函数检查,最后返回true。
public int set(String source, String target, int weight)函数需要完成的功能较为复杂,不仅需要能够将一条边加入到边的集合中,同时需要能够对这条边进行更新、删除。所以我们首先根据输入的两个顶点参数判断这两个顶点之间是否存在一条边,如果存在这条边的情况下,我们先将这条边的权值保存下来,然后将其从边集合中删除出去。接下来就是根据输入的第三个参数进行不同的处理。如果权值大于0,那么我们就在这两个顶点中新建一条边,并且返回刚才保存的权值,这样能够完成增加、更新一条边的功能。相反,如果输入的参数等于0的话,那么我们直接返回刚才得到的边的权值。
public boolean remove(String vertex)函数是为了删除一个在顶点集合中的顶点。如果输入的参数不存在顶点集合中,那么自然我们就直接返回false。如果存在于顶点集合中,我们需要将这个顶点所来联系的所有边进行删除。在操作结束的时候还要将这个顶点一起删除,最后返回true。
public Set<String> vertices()是为了得到所有的顶点集合,为了防止表示泄露,所以我们这里应该返回一个拷贝的对象。
public Map<String, Integer> sources(String target)是返回一个终点对应的所有原点以及它们之间的边的权值。
public Map<String, Integer> targets(String source)函数和上面这个函数类似,都是为了得到一个原点所对应的所有终点和它们之间边的权值之间的关系。
public String toString()是实现过程中的最后一个函数,它重写了打印函数,为了更好显示图形中所有边的信息,同时也是为了更好对图形结构进行打印。

Implement ConcreteVerticesGraph

这一部分的实现需要根据顶点类进行设计。因此我们先进行顶点的设计。顶点的设计方式相比较而言来说更复杂一些。因为我们需要通过设置顶点之间的关系来得到在图中实际存在的边。因此我们设计的属性为:

    private final String vertexlabel;
	private final Map<String,Integer> sourcesmap = new HashMap<>();
	private final Map<String,Integer> targetsmap = new HashMap<>();

其中我们设计的方法相较于边类的设计方法就更复杂一些。首先我们需要设计检查函数,判断顶点的表示是否符合要求。之后就是3个get函数,为了防止表示泄露,我们设计了防御式拷贝的方法来避免出现这种情况。在顶点类的设计中,我们还添加了增加边和删除边的操作。它们的具体实现如下,其中设置出边和入边、删除出边和入边实现基本一致,这里选择出边进行讨论:

     /**
	 * 在这个点中设置、更新或删除一条出边
	 * @param target 达到的顶点标记
	 * @param weight 设置的边权值
	 * @return 如果权值为0,删除这条边,如果之前有边,返回原来权值,否则返回0
	 */
	public int setEdgeto(String target,int weight) {
		if(weight == 0) {
			return removeEdgeto(target);
		}
		Integer preWeight = targetsmap.put(target,weight);
		if(preWeight != null) {
			return preWeight;
		}
		return 0;
	}
	/**
	 * 将一条出去的边删除
	 * @param target 到达的终点标记
	 * @return 如果没有这个顶点返回0,否则返回权值
	 */
	public int removeEdgeto(String target) {
		Integer weight = targetsmap.remove(target);
		if(weight != null) {
			return weight;
		}
		return 0;
	}

设计完成之后,我们还需要重写打印函数使得信息的打印更清楚,同时也能够方便对测试函数进行编写。完成上述这些功能之后,我们就可以开始ConcreteVerticesGraph类的设计。由于采用顶点的设计思路进行实现,因此属性只有一个:
private final List<Vertex> vertices = new ArrayList<>();
之后就是一些Graph接口中定义的方法的实现:
public boolean add(String vertex)是用来在顶点集合中添加一个顶点。由于不能出现相同标识的顶点,因此我们需要通过遍历顶点集合,得到它们的标识,和我们输入的标识进行比较,从而得到这个顶点是否在图中已经出现过。如果出现过那么直接返回false,否则将输入标识转化为一个顶点类,添加进入顶点的列表中,同时检查表示不变性,返回true。
public int set(String source, String target, int weight)是用来设置顶点之间的边的。由于顶点必须先在顶点集合中出现,因此我们先将顶点加入到顶点集合中,然后遍历所有的顶点,如果某个点的原点和终点和输入参数一致,那么就对应设置终点和原点,同时将权值进行保存,最后进行返回。
public boolean remove(String vertex)是用来删除顶点的。首先我们需要判断顶点是否在顶点集合中,因此我们先设计标志变量用来保存是否发现了输入参数。然后进行遍历顶点,将这个点和输入参数相关的点从原点集合以及终点集合中全部删除,最后返回是否找到这个输入参数。
public Set<String> vertices()函数是为了返回所有顶点的标志信息,因此我们遍历所有的顶点,然后得到所有的顶点的标志,加入到一个集合当中,并且最后返回这个集合。
public Map<String, Integer> sources(String target)是为了得到某个顶点所包含的所有边的信息。因此我们对顶点集合进行遍历,如果得到某个点一致,那么利用他的所有原点得到返回值。
public Map<String, Integer> targets(String source)是为了得到所有的终点信息。与上面的方法类似,都是先进行遍历,得到相同之后再利用他的所有终点进行返回。
public String toString()是对打印函数的一个重写,为了更好的打印出图形所包含的顶点信息和边的信息。

Implement generic Graph

在这个问题中,我们需要对前面完成的两个具体实现进行拓展,需要使其能够支持泛型的操作,而不应该只是仅仅支持某种特殊的类型。因此我们需要进行修改。

Poetic walks

这个部分是根据我们实现的图形结构,对输入的文件按照每个词作为一个顶点生成一个图,然后输入一个字符串,根据这个图为这个字符串添加桥接词,然后进行输出。

Implement GraphPoet

这个任务需要完成生成图形功能和根据输入的字符串打印出添加桥接词的功能。首先我们根据输入的文件对词语进行提取和生成。具体的实现需要根据图形结构进行实现。实现之后根据输入字符串进行词语的添加,添加的过程需要判断找到一个最大权值的字符串,这一部分的具体实现如下:

Graph poetry slam

这一部分需要我们根据上面的设计实行一个生成诗歌的功能。因此我们从网络上选择了几首诗歌放置在一个文件中,然后输入几个词语根据上面的诗歌进行词语的添加,具体的实例截图如下:

    final GraphPoet nimoy = new GraphPoet(new File("src/P1/poet/poem.txt"));
    final String input = "Love more than word, I in love I feel touch.";
    System.out.println(input + "\n>>>\n" + nimoy.poem(input));

具体实现效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值