最短路径算法是算法课上的一项重要内容。周末看了网易公开课上的那门算法导论,从第17课开始讲关于图的问题。由于语言的关系,看的不是太明白。后来,只好拿起纸和笔,对照书,一步一步地写,才明白dijkstra算法(以下简称D算法)的过程。但是,明白是一回事,用代码实现又是另外一回事。所以,又花了几个小时的时间,程序才算是运行正常,得到正确答案。快泪奔了。程序现在还仍谈不上什么性能,仅是运行而已。
如果说有值得总结的,对自己而言,第一,写程序还是晚上有效率;第二,开始CODE之前,还是需要用纸和笔,可能更效率;第三,是需要不断地练习。
D算法用到S、C两个顶点集合和一个整型数组D。其中S用来存放已选择的最短路径上的顶点;C用来存放未选择的顶点;D数组存放顶点1到其他顶点的最短路径的权值之和。S的初始值为顶点1,C的初始值为除顶点1之外的顶点,D的初始值是顶点1 到它直接指向的每个顶点权值,不直接指向的顶点,或者说,暂时不可达的顶点权值为正无穷大。设为正无穷大的原因,主要是算法在后面计算是否需要更该顶点的权值时用到。
1、初始化 S、C、D;
2、根据集合C中的顶点,查找D中最小值,找到该顶点后,将其放入S,同时在C中移除该顶点。
3、更新D值
4、重复2,直到C集合为空。
大致思路就是这样,如有不正确的地方,欢迎指正。JAVA代码如下:
import java.util.*;
/*
* Node:
*/
class Node {
int val;
Node() { val = 0; }
Node(int index) {
this.val = index;
}
void dispNode() {
System.out.print(this.val);
}
}
/*
* Edge:
*/
class Edge {
int val;
Node fromNode;
Node toNode;
Edge(){
val = 0;
fromNode = null;
toNode = null;
}
Edge(int v, Node from, Node to)
{
val= v;
fromNode = from;
toNode = to;
}
void dispEdge(){
System.out.print("<"+fromNode.val+","+toNode.val+":"+val+">");
}
}
/*
* Graph
*/
class Graph {
ArrayList<Node> nodes;
ArrayList<Edge> edges;
Graph(ArrayList<Node> n, ArrayList<Edge> e){
nodes = n;
edges = e;
}
void dispGraph(){
System.out.print("Node:\t");
for(Node n:nodes){
n.dispNode();
System.out.printf(" ");
}
System.out.println();
System.out.print("Edges:\t");
for(Edge e:edges )
{
e.dispEdge();
System.out.printf(" ");
}
System.out.println();
}
// for get L(u,v)
int min(int i,int j){
return ((i)<(j)) ? (i):(j);
}
void printState(ArrayList<Node> S,ArrayList<Node> C, int [] D)
{
System.out.println();
System.out.println("========================");
//display
System.out.print("S:\t{");
for(Node n: S)
System.out.print(n.val+" ");
System.out.print("}");
//display C
System.out.println();
System.out.print("C:\t{");
for (Node n: C)
System.out.print(n.val+" ");
System.out.print("}");
// display D
System.out.println();
System.out.print("D:\t[");
for (int i:D)
System.out.print(i+" ");
System.out.print("]");
System.out.println();
//display edges
//dispGraph();
}
/* find shortest path that from node 1 to each node of Graph */
void findShortestPath() {
// initiate S,C,D,v;
ArrayList<Node> S = new ArrayList<Node>();
ArrayList<Node> C = new ArrayList<Node>();
int[] D = new int[nodes.size()-1];
Node v = new Node();
// initiate S
S.add(nodes.get(0));
// initiate C
for (int i=1; i<nodes.size(); i++)
C.add(nodes.get(i));
// initiate D
int k=0;
for(Edge e:edges) {
if (e.fromNode.val == 1)
D[k++] = e.val;
}
for (int i=0; i<D.length-1; i++)
if (D[i] == 0)
D[i] = 10000;
// print S, C, D before start.
printState(S,C,D);
System.out.println();
// start to finding.
Iterator<Node> it = C.iterator();
while(it.hasNext()) {
// find minimal of D, for get v.
int id = 0;
int minimalOfD = D[0];
for(int i=1; i<C.size(); i++)
minimalOfD = min(minimalOfD,D[i]);
for(int i=0; i<C.size(); i++)
if(D[i] == minimalOfD)
id = i;
// initial v
v= C.get(id);
// print v
System.out.println("v = "+ v.val);
// update S, C
S.add(v);
C.remove(id);
// update D
int L = 0;
for (int i=0; i<C.size(); i++){
for (Edge e : edges){
if (e.fromNode.val == v.val && e.toNode.val == C.get(i).val) {
L = D[id]+ e.val;
D[e.toNode.val-2] = min(D[e.toNode.val-2],L);
printState(S,C,D);
}
}
}
}// _while
}// _findShortestPath()
} // _class Graph
class GraphDemo
{
public static void main (String[] args) {
// initiate Graph
int[][] edgesMatrix = {
{0,50,30,100,10},
{0,0,0,0,0},
{0,5,0,0,0},
{0,20,50,0,3},
{0,0,0,10,0}
};
int nodeNum = edgesMatrix.length;
ArrayList<Node> ns = new ArrayList<Node>();
ArrayList<Edge> es = new ArrayList<Edge>();
// add each Node
for(int i=1; i<= nodeNum; i++){
Node n = new Node(i);
ns.add(n);
}
// add each edge
for(int i=0; i<nodeNum; i++)
for(int j=0; j<nodeNum; j++)
if(edgesMatrix[i][j] != 0) {
Edge e = new Edge(edgesMatrix[i][j],ns.get(i),ns.get(j));
es.add(e);
}
// create the instance of Graph
Graph G = new Graph(ns,es);
// display the Nodes and Edges of Graph
G.dispGraph();
// find shortest-path from Node f to Node t
G.findShortestPath();
}
}