我正在研究
从书中算法的源代码获取单一源最短路径的queue-based
方法,此链接位于http://algs4.cs.princeton.edu/44sp/BellmanFordSP.java。Bellman-Ford algorithm
Robert Sedgewick and Kevin Wayne - Algorithms, 4th edition
我有两点,一个是疑问,另一个是代码改进建议。
在上述方法中,以下是用于放松顶点距离的放松方法的代码。
for (DirectedEdge e : G.adj(v)) { int w = e.to(); if (distTo[w] > distTo[v] + e.weight()) { distTo[w] = distTo[v] + e.weight(); edgeTo[w] = e; if (!onQueue[w]) { queue.enqueue(w); onQueue[w] = true; } } if (cost++ % G.V() == 0){ findNegativeCycle(); } }
在此方法中,在找到负循环之前使用以下条件。
if (cost++ % G.V() == 0){
findNegativeCycle();
}
在上面,他们将成本除以vertices
图表中的数量来检查negative cycle
。这可能是因为松弛是经过V-1
多次的,如果松弛持续Vth
一段时间,则意味着它有循环,其中 V 是顶点数。
但我认为在基于队列的方法中,他们使用除数定期检查是否发生循环。一个循环可以在上述条件为真之前或之后发生。如果在上述条件为真之后发生循环,则算法必须等到下一次条件为真才能检测到循环,如果为真,则循环不一定会发生(cost++ % G.V() == 0)
。所以我认为除数可以是任何足够小的数字,以便我们可以在适当的时间间隔后检查周期。我这样想对吗?
代码改进建议是,
findNegativeCycle()
如果发生循环,可以使用该方法返回 true。因此。这个条件——if (cost++ % G.V() == 0) { findNegativeCycle(); }
可以改成——
if (cost++ % G.V() == 0)
if(findNegativeCycle()){
return;
}
即使findNegativeCycle()
方法找到了循环,在代码中 for 循环也会继续运行。因此,如果发生循环,我们可以返回,而不是处理 for 循环的其余部分。
请分享您对以上 2 点的看法。提前致谢。