Dijkstra算法求单源最短路径Java实现

来源:互联网 发布:加强网络管理防范制止 编辑:程序博客网 时间:2024/05/19 06:17

如果所采用的实现方式合适,Dijkstra算法的运行时间要低于前面所说的Bellman_Ford算法,但是Dijkstra算法要求图中没有负边。Dijkstra算法在运行过程中维持的关键信息是一组结点集合S。从源结点s到该集合中每个结点之间的最短路径已经被找到。算法重复从结点集V-S中选择最短路径估计最小的结点u,将u加入到集合S,然后对所有从u发出的边进行松弛(有关松弛操作可见http://blog.csdn.net/john_bian/article/details/74612722)。下面是《算法导论》书中所给的伪代码:


在这个实现方式中,我们使用了一个最小优先队列Q来保存结点集合,每个结点的关键值为其d值。下面则是运用Dijkstra算法求解单源最短路径的过程的一个例子。


以下是用Java代码的具体实现

package test7;/** * 边 * @author sdu20 * */public class Edge {private int v1;private int v2;private int weight;public Edge(int v1,int v2,int weight){this.v1 = v1;this.v2 = v2;this.weight = weight;}public boolean equals(Edge edge){return this.v1==edge.getV1() && this.v2==edge.getV2() &&this.weight == edge.getWeight();}public int getV1(){return v1;}public int getV2(){return v2;}public int getWeight(){return weight;}public String toString(){String str = "[ "+v1+" , "+v2+" , "+weight+" ]";return str;}}

package test7;import java.util.*;/** * Dijkstra算法求解单源最短路径 * @author sdu20 * */public class Graph {private LinkedList<Edge>[] edgeLinks;private int vNum;//顶点数private int edgeNum;//边数private int[] distance;//存放v.dprivate int[] prenode;//存放前驱节点private LinkedList<Integer> S;//已经求到最短路径的顶点集合private LinkedList<Integer> Q;//尚未求到最短路径的顶点集合public static final int INF = 10000;//无穷大public static final int NIL = -1;//表示不存在public Graph(int vnum){this.vNum = vnum;edgeLinks = new LinkedList[vnum];edgeNum = 0;distance = new int[vnum];prenode = new int[vnum];for(int i = 0;i<vnum;i++)edgeLinks[i] = new LinkedList<>();}public void insertEdge(Edge edge){int v1 = edge.getV1();edgeLinks[v1].add(edge);edgeNum++;}public void bianli(){System.out.println("共有 "+vNum+" 个顶点, "+edgeNum+" 条边");for(int i = 0;i<vNum;i++){LinkedList<Edge> list = (LinkedList<Edge>) edgeLinks[i].clone();while(!list.isEmpty()){Edge edge = list.pop();System.out.println(edge.toString());}}}/** * 对最短路径估计和前驱节点进行初始化 * @param start */public void INITIALIZE_SINGLE_SOURCE(int start){for(int i = 0;i<vNum;i++){distance[i] = INF;prenode[i] = NIL;}distance[start] = 0;}/** * 松弛 * @param edge */public void RELAX(Edge edge){int v1 = edge.getV1();int v2 = edge.getV2();int w = edge.getWeight();if(distance[v2]>distance[v1]+w){distance[v2] = distance[v1]+w;prenode[v2] = v1;}}/** * Dijkstra算法实现 * @param start */public void DIJKSTRA(int start){INITIALIZE_SINGLE_SOURCE(start);S = new LinkedList<>();Q = new LinkedList<>();for(int i = 0;i<vNum;i++){Q.add(i);}while(!Q.isEmpty()){int u = EXTRACT_MIN(Q);S.add(u);LinkedList<Edge> list = (LinkedList<Edge>) edgeLinks[u].clone();while(!list.isEmpty()){Edge edge = list.pop();RELAX(edge);}}ShowResult();}private int EXTRACT_MIN(LinkedList<Integer> q){if(q.isEmpty())return -1;int min = q.getFirst();for(int i = 0;i<q.size();i++){int v = q.get(i);if(distance[min]>distance[v]){min = v;}}int min2 = min;q.remove(q.indexOf(min));return min;}private void ShowResult(){System.out.println("=========Result==========");Stack<Integer>[] routes = new Stack[vNum];for(int i = 0;i<vNum;i++){routes[i] = new Stack<>();int j = i;while(j != NIL){routes[i].push(j);j = prenode[j];}System.out.print(i+"("+distance[i]+") : ");while(!routes[i].isEmpty()){int k = routes[i].pop();System.out.print("-->"+k);}System.out.println();}}}

package test7;public class Main {public static void main(String[] args) {// TODO Auto-generated method stubbookGraph();}private static void bookGraph(){Graph graph = new Graph(5);Edge[] edges = new Edge[10];edges[0] = new Edge(0,1,10);edges[1] = new Edge(0,3,5);edges[2] = new Edge(1,2,1);edges[3] = new Edge(1,3,2);edges[4] = new Edge(2,4,4);edges[5] = new Edge(3,1,3);edges[6] = new Edge(3,2,9);edges[7] = new Edge(3,4,2);edges[8] = new Edge(4,0,7);edges[9] = new Edge(4,2,6);for(int i = 0;i<10;i++)graph.insertEdge(edges[i]);graph.bianli();graph.DIJKSTRA(0);}}

运行截图如下所示