全部代码 https://github.com/Joshmomel/Princeton_Algorithms/tree/wordnet/src
背景
这次作业需要先构造一个wordnet, 然后在此基础上找出两组次的最短距离
wordnet是单词指向上位词的一个网络
SAP
需求
根据FAQ 的Possible progress steps, 我们先要完成SAP. 也就是输入一个Digraph, 点v, 点w, 就算出最短共同祖先 (shortest ancestral path), 以及最短距离.
比如左图, 点3跟10的最短共同祖先就是1, 他们的距离是4
比如右图, 点1跟点5的最短共同祖先就是0, 他们的距离是2
算法分析
- 对点v做一次BFS, 使用mapV记录下经过的点以及其距离, {vertices: distance}
- 设置两个variable, node以及count, 初始值为-1, 用于储存下面的最短距离以及祖先用
- 对点w做一次BFS, 如果点n同时也经过mapV, 那么计算一下点v跟w的距离, 如果比count少, 则跟新count, 并且把node指向n
BreadthFirstDirectedPaths bfsFromV = new BreadthFirstDirectedPaths(G, v);
BreadthFirstDirectedPaths bfsFromW = new BreadthFirstDirectedPaths(G, w);
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < G.V(); i++) {
if (bfsFromW.hasPathTo(i)) {
map.put(i, bfsFromW.distTo(i));
}
}
int node = -1;
int count = -1;
for (int i = 0; i < G.V(); i++) {
var find = map.get(i);
if (find != null && bfsFromV.hasPathTo(i)) {
var total = find + bfsFromV.distTo(i);
if (count == -1 || total < count) {
count = total;
node = i;
}
}
}
上面的count就是lenght, node就是ancestor
性能提升
当然, 除了算法这个SAP还需要考虑在call length(int v, int w), ancestor(int v, int w) 怎么不用重复调用BFS, 毕竟调用一次就能同时算出length以及ancestor 我的方法是通过map存起来
具体来说, 构建一个VwPair类
private static class VwPair {
int v;
int w;
public