我正在做代码强制,并希望使用带有邻接矩阵的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循环设置为已解决的答案。所以换句话说,它只适用于这个问题/图表,因为我先用手解决了。
以下是我的问题基于的示例图表的图形表示:
答案 0 :(得分:1)
我认为你要找的主要答案是你应该让while循环运行直到Q1为空。你正在做的事情本质上是最好的搜索。但是,由于您的代码有点不正统,因此需要进行更多更改。
通常,Dijkstra的算法与优先级队列一起使用。 Q1是您的&#34;待办事项列表&#34;据我所知,你的代码。 Dijkstra的规范说明接下来应该探索最接近起始顶点的顶点,因此不应该使用ArrayList,而是应该使用Q1的PriorityQueue,根据最接近起始顶点的顶点对顶点进行排序。最常见的Java实现将PriorityQueue
与元组类一起使用:一个内部类,它存储对顶点的引用和&#34;距离&#34;到起始顶点。 Dijkstra的规范还规定,如果发现一个新的边缘使顶点更靠近起点,则应该在优先级队列中的条目上使用DecreaseKey操作,以使顶点更早出现(因为它现在更近了)。但是,由于PriorityQueue
不支持该操作,因此只会在队列中添加一个全新的条目。如果你有一个支持这个操作的堆的良好实现(我自己创建了一个,here),那么reduceKey可以显着提高效率,因为你不再需要创建那些元组。
所以我希望这是一个足够的答案:做一个合适的&#39; todo&#39; list而不是Q1,为了使算法通用,让while循环运行直到todo列表为空。
编辑:我根据您的格式制作了一个实现,似乎有效:
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