Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多个加速Dijkstra的解决方案会降低性能吗?_Java_Algorithm_Graph Algorithm_Path Finding - Fatal编程技术网

Java 多个加速Dijkstra的解决方案会降低性能吗?

Java 多个加速Dijkstra的解决方案会降低性能吗?,java,algorithm,graph-algorithm,path-finding,Java,Algorithm,Graph Algorithm,Path Finding,我已经实现了一个通用的Dijkstra搜索: public void search(Vertex source) { source.minDistance = 0; PriorityQueue<Vertex> vertexQueue = new PriorityQueue<Vertex>(); vertexQueue.add(source); while (!vertexQueue.isEmpty()) { Vertex

我已经实现了一个通用的Dijkstra搜索:

public void search(Vertex source) {
    source.minDistance = 0;

    PriorityQueue<Vertex> vertexQueue = new PriorityQueue<Vertex>();
    vertexQueue.add(source);

    while (!vertexQueue.isEmpty()) {
        Vertex u = vertexQueue.poll();

        for (Edge e : u.edges) {
            Vertex v = e.target;

            int weight = e.weight;
            int distance = u.minDistance + weight;

            if (distance < v.minDistance) {
                vertexQueue.remove(v);

                v.minDistance = distance ;
                v.previous = u;

                vertexQueue.add(v);
            }
        }
     }
}
公共无效搜索(顶点源){
source.minDistance=0;
PriorityQueue vertexQueue=新建PriorityQueue();
添加(源);
而(!vertexQueue.isEmpty()){
Vertex u=vertexQueue.poll();
对于(边e:u边){
顶点v=e.目标;
int-weight=e.weight;
内部距离=u.minDistance+重量;
if(距离小于v.minDistance){
移除(v);
v、 距离=距离;
v、 先前=u;
vertexQueue.add(v);
}
}
}
}
加速的方法包括:

  • 斐波那契堆
  • 双向搜索
此搜索将用作使用Yen算法实现k-最短路径的基础

在算法上同时应用这两种加速是否会提高搜索时间,还是会因为两者都在使用而导致性能损失


此外,是否可以实现进一步的加速?

java.util.PriorityQueue.remove是一种O(n)操作。如果要使用此PriorityQueue,最好在PriorityQueue中允许重复顶点,但仅在第一次轮询顶点时处理该顶点:

class Vertex {
    // existing members

    boolean visited;
}

虽然这会将优先级队列的大小增加多达d(最大节点度)的一倍,因此会将运行时更改为O(dn log(nd)),即O(dn(logn+logd)),但如果d很小,这可能是可以接受的。特别是,如果d是常数(这在许多实际的路径查找问题中都是如此),那么该算法就是O(n logn)

使用基于指针的堆实现(如fibonacci堆)可以通过提供成本降低操作来有效防止堆中的重复,但基于指针的数据结构的常量因子比基于数组的优先级队列要差。此外,fibonacci堆的陡峭度是常数因子,在每次操作中需要接触更多的节点。因此,我怀疑它实际上会比具有重复项的二进制堆慢(假设节点相当小)

对于双向搜索,我想你的意思是从两端“平行”运行Dijkstra,直到两者相遇?这种优化将独立于队列表示的改进,并且可以很好地结合起来


另一个可能的改进是通过利用Yen算法的后续Dijkstra调用的相似性来减少调用Dijkstra的频率。是否值得修改迪杰克斯特拉,这样我们就可以倒带它,而不是从头开始?唉,我不太了解Yen算法,所以我无法评估这是否有帮助。

我确实认为使用Fibonacci堆会更快,尽管您可能只会注意到如果多次调用此函数。使用回溯也可能会有更大的帮助

但是,我建议不要使用Yen的算法,而是使用K*算法,它基本上允许您使用A*来解决K-最短路径问题!K*还有一些其他的好处,特别是对于非常大的图的内存使用

你可以在这里找到这篇论文的免费副本:(我想这篇论文还有一个更新的更长的版本)


希望这能有所帮助。

斐波那契堆的问题是它们的常数很差。在使用原始优先级队列(任意删除
O(n)
和fibonacci堆(常数较差)之间有一些中间点)。@amit取决于具体情况。如果距离相差很大,那就更好了
        Vertex u = vertexQueue.poll();
        if (u.visited) continue;
        u.visited = true;