全部代码:https://github.com/RedemptionC/CourseraAlgorithms/tree/master/wordnet
这是学习完有向图,无向图之后的编程作业,我们要提交的是三个类:
SAP(shortest ancestor path) :
输入是一张有向图,实现这样一些函数:给出两个点,求他们的最短祖先路径长度,如果没有就返回-1
这里的最短祖先路径是指:假设v,w有一个公共祖先x,对应的祖先路径是v-x,x-w之间的有向路径,两条路径长度之和最小时,就是最短祖先路径
如图:
除了点与点的最短祖先路径,还要求计算点集与点集之间的最短祖先路径
首先是求两点的sap:
private void setSAP(int v, int w) {
validateV(v);
validateV(w);
BreadthFirstDirectedPaths breadthFirstDirectedPathsV = new BreadthFirstDirectedPaths(
digraph, v);
BreadthFirstDirectedPaths breadthFirstDirectedPathsW = new BreadthFirstDirectedPaths(
digraph, w);
HashSet<Integer> setV = new HashSet<>();
for (int i = 0; i < digraph.V(); i++) {
// 这里是包括自己的,因为如果A->B,那么B也可以是SAP上的公共祖先
// 记录所有v能够到达的点,放进set
if (breadthFirstDirectedPathsV.distTo(i) != Integer.MAX_VALUE)
setV.add(i);
}
ancestor = null;
minDistance = Integer.MAX_VALUE;
for (int i = 0; i < digraph.V(); i++) {
// 处理所有w能到达,并且在set里(v也能到达)的点
if (breadthFirstDirectedPathsW.distTo(i) != Integer.MAX_VALUE && setV.contains(i)) {
// 计算他们的距离之和,保存产生最小值时的祖先(即他们的到达的公共点)
int t = breadthFirstDirectedPathsV.distTo(i) + breadthFirstDirectedPathsW.distTo(i);
if (t < minDistance) {
minDistance = t;
ancestor = i;
}
}
}
this.v = v;
this.w = w;
if (minDistance == Integer.MAX_VALUE)
minDistance = -1;
if (ancestor == null)
ancestor = -1;
}
首先调用提供的BFS库,将v,w分别作为遍历的起点,算出pathTo,和distTo数组(这里出于各种原因考虑使用了现有的库,没有自己实现,因此在本文最后面会附上这个库的笔记),其中distTo[v]记录了起点s与v之间的距离
然后将v出发能到达的点加入到一个set,之后遍历w出发能到达,并且也出现在set中(即v能到达)的点,计算该祖先路径的长度,保存最小的,并且记下sap对应的祖先节点
然后是两个点集之间的sap: