我正在尝试使用JGraphT实现Prim的最小生成树算法。它看起来怎么样?
我遇到的一个问题是JGraphT对所有内容的处理。因此,如果不恰当的话,有时需要进行一些尴尬的调用来反转g.getEdgeSource(e)
和g.getEdgeTarget(e)
。
我试图用JGraphT的Fibonacci Heap来实现它,但它太难了所以我只是做了一个普通的PQ。
我没有将不存在的边的权重设置为无穷大,而是将其添加到队列中。
么?文体问题?明显效率低下?代码我应该使用而不是自己滚动?
public static Graph<String, DefaultWeightedEdge> primPQ(final WeightedGraph<String, DefaultWeightedEdge> g, String root) {
Graph<String, DefaultWeightedEdge> mst = new SimpleWeightedGraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
Queue<DefaultWeightedEdge> pq = new PriorityQueue<DefaultWeightedEdge>(g.vertexSet().size(), new Comparator<DefaultWeightedEdge>() {
@Override
public int compare(DefaultWeightedEdge o1, DefaultWeightedEdge o2) {
if (g.getEdgeWeight(o1) < g.getEdgeWeight(o2)) {
return -1;
}
if (g.getEdgeWeight(o1) > g.getEdgeWeight(o2)) {
return 1;
}
return 0;
}
});
mst.addVertex(root);
DefaultWeightedEdge link;
for (String v : g.vertexSet()) {
link = g.getEdge(root, v);
if (link != null) {
pq.add(link);
}
}
//this is made difficult by JGraphT's assumption that everything is directed
DefaultWeightedEdge minEdge = pq.poll();
String toAdd;
String alreadyFound;
String tmp;
while (minEdge != null) {
// guessing at which is in the MST
toAdd = g.getEdgeTarget(minEdge);
alreadyFound = g.getEdgeSource(minEdge);
if (!(mst.containsVertex(toAdd) && mst.containsVertex(alreadyFound))) {
// swap if backwards
if (mst.containsVertex(toAdd)) {
tmp = toAdd;
toAdd = alreadyFound;
alreadyFound = tmp;
}
mst.addVertex(toAdd);
mst.addEdge(alreadyFound, toAdd, minEdge);
System.out.format("%s --> %s\n", g.getEdgeSource(minEdge), toAdd);
for (String v : g.vertexSet()) {
if (! mst.containsVertex(v)) {
link = g.getEdge(toAdd, v);
if (pq.contains(link)) {
g.setEdgeWeight(minEdge, Math.min(g.getEdgeWeight(minEdge), g.getEdgeWeight(link)));
}
if (link != null && ! pq.contains(link)) {
pq.add(link);
}
}
}
}
minEdge = pq.poll();
}
return mst;
}
答案 0 :(得分:1)
我已经将你的算法的结果与一个作为家庭作业的矿井进行了比较,并且它们都给出了相同的最小总重量,并将其保持下去!
答案 1 :(得分:0)
在增加边数和顶点数的同时,我得到不同的结果,我会回来......
答案 2 :(得分:0)
好的,现在看起来很好。
顺便说一下,我的练习有点棘手:我必须编写一个算法来确实找到最小的生成树,但我的算法必须通过边缘消除来进行。我写了一些东西,使用一些深度优先遍历来寻找周期,然后通过“着色”红色来消除最大的加权边缘。
对于4个随机生成的图表,您的PRIM alg产生与我的alg相同的最小总重量,其中N = 200个节点,并且对于k = 2,3,4,各种值M =(N *(N-1)/ k) ,8为边数。
乍一看,我认为这种测试有点矫枉过正,但事实并非如此!