Skip to content

Latest commit

 

History

History

Directed Graphs

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

1. 题目阅读

WordNet定义

WordNet是指一个包含唯一根的有向无环图,图中每一组词表示同一集合,每一条边v→w表示w是v的上位词。和树不同的地方是,每一个子节点可以有许多父节点。

输入格式

  • 同义词表

文件中每行包含一次同义名词。首先是序号;然后是词,用空格分开。若为词组,则使用下划线连接词组。最后是同义名词的注释

36,AND_circuit AND_gate,a circuit in a computer that fires only when all of its inputs fire

  • 上位词表

文件中包含序号i的上位词j。若有多个上位词,则使用空格分隔。

34,47569,48084

WordNet数据类型

需要实现

  • 构造函数,通过同义词表和上位词表
  • 迭代器
  • 判断词是否在WordNet里
  • 计算两个词的最短祖先路径距离
  • 计算两个词的最短祖先路径

最短祖先路径是指两个点v、w到达相同点距离和最短的点x。

另外,还可以给定两个集合A、B,两个集合中的各自拥有一个点v、w到达相同点距离和最短的点,对比第一种,还需要从集合中找出合适的v、w。

SAP数据类型(最短祖先路径)

需要实现

  • 求两集合的最短祖先编号、距离

Outcast detection

给定一串词,给出哪个词和其他词最不相关

2. 题目分析

按照我认为的实现顺序分析

SAP实现

构造函数:构造digraph

祖先编号,路径: 寻找两个点v、w到达相同点距离的最短点x。

第一步,对v、w进行BFS搜索,找到从v、w到其他点的最短距离。BFS是O(E + V)

第二步,将v、w到相同点的距离相加,若其中一个点不能到达,则这个点的最短祖先距离为-1。在这个遍历过程中,找到相加距离最短的点则为最短祖先距离。O(V)

整个算法性能:O(E + V)

卡在这里了一会,主要是读题目的checklist时候看到bfs当成深度优先了,然后思想就被禁锢dfs了

两个集合的最短祖先

两个集合两两求,找最小。感觉这个肯定超时了。但是感觉也只能这样。暂时用这个方法写。

正确实现方法:BFS提供使用一个集合作为参数构造BFS的,得到的是点到集合的最短距离,由于不需要输出路径,这里你可以认为一个集合就是一个点,就可以按照上面的方法来计算两个集合的最短祖先了。

WordNet实现

构造函数:文件读取,使用java的string分割。然后构造一个digraph。

关于文件存储

这里的输入都是string,不是序号,需要先将单词对应为序号。

构造一个类存储同义词集合,包括序号和单词。第一句是错的,不需要构造这个,因为这里不需要知道一个序号下面有什么单词。第二句也是错的,因为sap的输出需要输出单词,还是需要构造一个map存序号和单词的关系。但是api只输出一个单词,不懂为什么。这里api是要输出那一串用空格分开的词。

同义词组:使用一个map存储单词所对应的序号。这里求出最大的序号,就知道digraph有多少个顶点,可以构造空digraph。

上位词关系:使用一个digraph存储

迭代器:返回map的key的迭代器

最短祖先路径、距离:调用sap

边界条件:判断是否有环,调用DirectedCycle类。判断是否有多个root,如果一个点有一个出的边,则不是root。

Outcast detection

构造函数:因为需要immutable,要拷贝WordNet。暂时先不考虑这个,直接引用参数里的wordnet。

上面直接引用没啥问题。java的immutable还是没太搞懂

outcast:计算每个输入词和其他词的距离,输出最大的

3. 第一次提交的问题

corner case的异常抛出不全

迭代器里有null的没考虑,isnoun参数为null没考虑

WordNet的sap返回值错误

应该返回所有的词,用空格分开,跟输入一样的方式,而不是只返回一个词。

集合的最短祖先求解超时

果然超时了。参考了别人的博文,直接使用BFS好像是不行的,需要自己实现才能解决时间。决定自己写了。

准备自己写BFS时,发现作者提供的BFS是有点到集合的最短距离的构造方法,用这个就可以。分析已经写在上文

4. 运行时间分析

由于SAP中的length和ancestor都是调用了同样的函数,所以时间相同。

都是两个BFS加上一个对所有顶点的遍历。BFS是的时间是O(E + V),则这里可以认为是~(2E + 3V)。用大O法表示还是O(E + V)。

因为这里是调用的库中的BFS,所以运行时间最优和最差是一样的。

5. ToDo: 性能优化

想快速的把课程搞完,所以这里性能优化的程序先不写了。这里暂时只完成性能优化的程序的分析,分析checklist里面三个优化条件。

都是在优化sap

  • 第一个没看懂
  • 第二个就是自己实现BFS,不是一次性跑完BFS,而是两个点v、w交替运行BFS,当出现第一个点x被两个点都访问过时,这个点就是最短祖先。
  • 第三个是加一个缓存,缓存上一次的v、w和其祖先信息,如果新的请求的v、w相同,则直接输出,不需要再搜索。

参考

1.Programming Assignment 1: WordNet