【问题标题】:Dijkstra's Dilema: How can I make my Algorithm abstract?Dijkstra 的困境:如何使我的算法抽象化?
【发布时间】:2014-10-04 01:19:17
【问题描述】:

我正在执行代码强制,并希望使用带有邻接矩阵的 Java 为有向图实现 Dijkstra 的最短路径算法,但我很难使其适用于除编码处理的尺寸之外的其他尺寸。

这是我的工作代码

int max = Integer.MAX_VALUE;//substitute for infinity

    int[][] points={//I used -1 to denote non-adjacency/edges
            //0, 1, 2, 3, 4, 5, 6, 7
            {-1,20,-1,80,-1,-1,90,-1},//0
            {-1,-1,-1,-1,-1,10,-1,-1},//1
            {-1,-1,-1,10,-1,50,-1,20},//2
            {-1,-1,-1,-1,-1,-1,20,-1},//3
            {-1,50,-1,-1,-1,-1,30,-1},//4
            {-1,-1,10,40,-1,-1,-1,-1},//5
            {-1,-1,-1,-1,-1,-1,-1,-1},//6
            {-1,-1,-1,-1,-1,-1,-1,-1} //7
            };
    int [] record = new int [8];//keeps track of the distance from start to each node
    Arrays.fill(record,max);
    int sum =0;int q1 = 0;int done =0;
    ArrayList<Integer> Q1 = new ArrayList<Integer>();//nodes to transverse 
    ArrayList<Integer> Q2 = new ArrayList<Integer>();//nodes collected while transversing
    Q1.add(0);//starting point
    q1= Q1.get(0);
    while(done<9) {// <<< My Problem
        for(int q2 = 1; q2<8;q2++) {//skips over the first/starting node
            if(points[q1][q2]!=-1) {//if node is connected by an edge
                if(record[q1] == max)//never visited before
                    sum=0;
                else 
                    sum=record[q1];//starts from where it left off
                int total = sum+points[q1][q2];//total distance of route
                if(total < record[q2])//connected node distance
                    record[q2]=total;//if smaller
                Q2.add(q2);//colleceted node
            }
        }
        done++;
        Q1.remove(0);//removes the first node because it has just been used
        if(Q1.size()==0) {//if there are no more nodes to transverse
            Q1=Q2;//Pours all the collected connecting nodes to Q1
            Q2= new ArrayList<Integer>();
            q1=Q1.get(0);
        }
        else//
            q1=Q1.get(0);//sets starting point 
    }![enter image description here][1]

但是,我的算法版本只有效,因为我将 while 循环设置为已解决的答案。所以换句话说,它只适用于这个问题/图表,因为我先手动解决了它

我怎样才能使它适用于所有规模的所有组?

这是我的问题所基于的示例图的图示:

【问题讨论】:

    标签: java algorithm graph dijkstra shortest-path


    【解决方案1】:

    我认为您正在寻找的主要答案是您应该让 while 循环运行直到 Q1 为空。您所做的基本上是最佳优先搜索。不过,由于您的代码有点不正统,因此需要进行更多更改。

    通常,Dijkstra 算法与优先级队列一起使用。正如我从您的代码中了解到的那样,Q1 是您的“待办事项列表”。 Dijkstra 的规范说接下来应该探索最接近起始顶点的顶点,因此您应该使用 Q1 的 PriorityQueue 而不是 ArrayList,它根据最接近起始顶点的顶点对顶点进行排序。最常见的 Java 实现使用 PriorityQueue 和一个元组类:一个内部类,它存储对顶点的引用和到起始顶点的“距离”。 Dijkstra 的规范还规定,如果发现新边使顶点更接近起点,则应在优先级队列中的条目上使用 DecreaseKey 操作以使顶点更早出现(因为它现在更接近) .但是,由于PriorityQueue 不支持该操作,因此只需将一个全新的条目添加到队列中。如果您有一个支持此操作的良好堆实现(我自己做了一个,here),那么 reductionKey 可以显着提高效率,因为您不再需要创建这些元组。

    所以我希望这是一个足够的答案:制作一个适当的“待办事项”列表而不是 Q1,并且为了使算法通用,让 while 循环运行直到待办事项列表为空。

    编辑:我根据你的格式为你做了一个实现,这似乎有效:

    public void run() {
        final int[][] points = { //I used -1 to denote non-adjacency/edges
            //0, 1, 2, 3, 4, 5, 6, 7
            {-1,20,-1,80,-1,-1,90,-1}, //0
            {-1,-1,-1,-1,-1,10,-1,-1}, //1
            {-1,-1,-1,10,-1,50,-1,20}, //2
            {-1,-1,-1,-1,-1,-1,20,-1}, //3
            {-1,50,-1,-1,-1,-1,30,-1}, //4
            {-1,-1,10,40,-1,-1,-1,-1}, //5
            {-1,-1,-1,-1,-1,-1,-1,-1}, //6
            {-1,-1,-1,-1,-1,-1,-1,-1}  //7
        };
        final int[] result = dijkstra(points,0);
        System.out.print("Result:");
        for(final int i : result) {
            System.out.print(" " + i);
        }
    }
    
    public int[] dijkstra(final int[][] points,final int startingPoint) {
        final int[] record = new int[points.length]; //Keeps track of the distance from start to each vertex.
        final boolean[] explored = new boolean[points.length]; //Keeps track of whether we have completely explored every vertex.
        Arrays.fill(record,Integer.MAX_VALUE);
        final PriorityQueue<VertexAndDistance> todo = new PriorityQueue<>(points.length); //Vertices left to traverse.
        todo.add(new VertexAndDistance(startingPoint,0)); //Starting point (and distance 0).
        record[startingPoint] = 0; //We already know that the distance to the starting point is 0.
        while(!todo.isEmpty()) { //Continue until we have nothing left to do.
            final VertexAndDistance next = todo.poll(); //Take the next closest vertex.
            final int q1 = next.vertex;
            if(explored[q1]) { //We have already done this one, don't do it again.
                continue; //...with the next vertex.
            }
    
            for(int q2 = 1;q2 < points.length;q2++) { //Find connected vertices.
                if(points[q1][q2] != -1) { //If the vertices are connected by an edge.
                    final int distance = record[q1] + points[q1][q2];
                    if(distance < record[q2]) { //And it is closer than we've seen so far.
                        record[q2] = distance;
                        todo.add(new VertexAndDistance(q2,distance)); //Explore it later.
                    }
                }
            }
    
            explored[q1] = true; //We're done with this vertex now.
        }
        return record;
    }
    
    private class VertexAndDistance implements Comparable<VertexAndDistance> {
        private final int distance;
        private final int vertex;
    
        private VertexAndDistance(final int vertex,final int distance) {
            this.vertex = vertex;
            this.distance = distance;
        }
    
        /**
         * Compares two {@code VertexAndDistance} instances by their distance.
         * @param other The instance with which to compare this instance.
         * @return A positive integer if this distance is more than the distance
         * of the specified object, a negative integer if it is less, or
         * {@code 0} if they are equal.
         */
        @Override
        public int compareTo(final VertexAndDistance other) {
            return Integer.compare(distance,other.distance);
        }
    }
    

    输出:0 20 40 50 2147483647 30 70 60

    【讨论】:

      猜你喜欢
      • 2013-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 2021-12-24
      • 2011-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多