Java Prim';s MST至Dijkstra SPT
我遵循这本书的内容,在第294页中,它描述了通过修改Prim的最小生成树(MST)算法(我测试过并运行良好),我们可以使用经典的Dijkstra算法:将优先级分配从Java Prim';s MST至Dijkstra SPT,java,algorithm,Java,Algorithm,我遵循这本书的内容,在第294页中,它描述了通过修改Prim的最小生成树(MST)算法(我测试过并运行良好),我们可以使用经典的Dijkstra算法:将优先级分配从p=e->wt()边权重更改为p=wt[v]+e->wt()从源到边缘目标的距离。问题是,当我进行更改时,随后的条件从未计算为true,这是可以理解的wt是一个双数组,初始化为例如double.MAX_值因此,无论v和w是什么,该条件都不会成立(假设权重为非负): 你弄错了,因为v!=w、 wt[v]+e->wt()可以小于wt[w
p=e->wt()
边权重更改为p=wt[v]+e->wt()
从源到边缘目标的距离。问题是,当我进行更改时,随后的条件从未计算为true
,这是可以理解的wt
是一个双数组,初始化为例如double.MAX_值
因此,无论v
和w
是什么,该条件都不会成立(假设权重为非负):
- 你弄错了,因为v!=w、 wt[v]+e->wt()可以小于wt[w]。实际的错误是您需要设置
wt[source]=0
(dijkstra是单源最短路径,您需要一个源!)!关于这本书:如果他们忘了那一部分,他们的坏处是:-P谢谢。很好的捕获,但是算法仍然不起作用:(好的,我检查了发生了什么,条件if(wt[w]
永远不会为真,因为wt[min]
whenmin==source
为零。
P = wt[v] + e->wt();
if (P < wt[w]) { // this can never happen ... bug?
// ...
}
import java.util.*;
public class AdjacencyList {
//=============================================================
// members
//=============================================================
private static class Edge {
int source;
int target;
double weight;
};
private static class Vertex {
int index;
String name;
List<Edge> edges = new ArrayList<Edge>();
public Vertex(int index, String name) {
this.index = index;
this.name = name;
}
};
private static final int UNDEFINED = -1;
private int edgesCount = 0;
private final Vertex[] vertices;
private final boolean digraph;
private int orderCount;
//=============================================================
// public
//=============================================================
public AdjacencyList(int verticesCount, boolean digraph) {
this.vertices = new Vertex[verticesCount];
this.digraph = digraph;
}
public Vertex createVertex(int index) {
return createVertex(index, String.valueOf(index));
}
public Vertex createVertex(int index, String name) {
Vertex vertex = new Vertex(index, name);
vertex.index = index;
vertex.name = name;
vertices[index] = vertex;
return vertex;
}
public Edge addEdge(int begin, int end, double weight) {
return addEdge(vertices[begin], vertices[end], weight);
}
public Edge addEdge(Vertex begin, Vertex end, double weight) {
edgesCount++;
Edge edge = new Edge();
edge.source = begin.index;
edge.target = end.index;
edge.weight = weight;
vertices[begin.index].edges.add(edge);
if (!digraph) {
Edge reverse = new Edge();
reverse.source = end.index;
reverse.target = begin.index;
reverse.weight = edge.weight;
vertices[end.index].edges.add(reverse);
}
return edge;
}
// inefficient find edge O(V)
public Edge findEdge(int begin, int end) {
Edge result = null;
Vertex vertex = vertices[begin];
List<Edge> adjacency = vertex.edges;
for (Edge edge : adjacency) {
if (edge.target == end) {
result = edge;
break;
}
}
return result;
}
// inefficient remove edge O(V)
public void removeEdge(int begin, int end) {
edgesCount--;
removeOneEdge(begin, end);
if (!digraph) {
removeOneEdge(end, begin);
}
}
public final Vertex[] getVertices() {
return vertices;
}
public int getVerticesCount() {
return vertices.length;
}
public int getEdgesCount() {
return edgesCount;
}
public Vertex getSource() {
return vertices[0];
}
public Vertex getSink() {
return vertices[vertices.length - 1];
}
public void dijkstra() {
int verticesCount = getVerticesCount();
double[] wt = new double[verticesCount];
for (int i = 0; i < wt.length; i++) {
wt[i] = Double.MAX_VALUE;
}
wt[getSource().index] = 0.0;
Edge[] fr = new Edge[verticesCount];
Edge[] mst = new Edge[verticesCount];
int min = -1;
Edge edge = null;
for (int v = 0; min != 0; v = min) {
min = 0;
for (int w = 1; w < verticesCount; w++) {
if (mst[w] == null) {
double P = 0.0;
edge = findEdge(v, w);
if (edge != null) {
if ((P = wt[v] + edge.weight) < wt[w]) {
wt[w] = P;
fr[w] = edge;
}
}
if (wt[w] < wt[min]) {
min = w;
}
}
}
if (min != 0) {
mst[min] = fr[min];
}
}
for (int v = 0; v < verticesCount; v++) {
if (mst[v] != null) {
System.out.print(mst[v].source + "->" + mst[v].target + " ");
}
}
}
public void pushRelabel() {
// TODO
}
//=============================================================
// private
//=============================================================
private void removeOneEdge(int begin, int end) {
Vertex beginVertex = vertices[begin];
List<Edge> adjacency = beginVertex.edges;
int position = -1;
for (int i = 0; i < adjacency.size(); i++) {
if (adjacency.get(i).target == end) {
position = i;
break;
}
}
if (position != -1) {
adjacency.remove(position);
}
}
private static AdjacencyList createDijkstraGraph() {
int numberOfVertices = 6;
boolean directed = true;
AdjacencyList graph = new AdjacencyList(numberOfVertices, directed);
for (int i = 0; i < graph.getVerticesCount(); i++) {
graph.createVertex(i);
}
graph.addEdge( 0, 1, .41);
graph.addEdge( 1, 2, .51);
graph.addEdge( 2, 3, .50);
graph.addEdge( 4, 3, .36);
graph.addEdge( 3, 5, .38);
graph.addEdge( 3, 0, .45);
graph.addEdge( 0, 5, .29);
graph.addEdge( 5, 4, .21);
graph.addEdge( 1, 4, .32);
graph.addEdge( 4, 2, .32);
graph.addEdge( 5, 1, .29);
return graph;
}
/**
* Test main
*
* @param args
*/
public static void main(String[] args) {
// build the graph and test dijkstra shortest path
AdjacencyList directedDijkstra = createDijkstraGraph();
// expected:
System.out.println("\n\n*** testing dijkstra shortest path");
directedDijkstra.dijkstra();
}
}