迪科斯彻(Dijkstra)算法使用了广度优先搜索解决非负权有向图的单源最短路径问题,算法最终得到一个最短路径树。
在一个有向非负权重的图中,可以知道如AC>AB,这AC+CB>AB,这一不等式有点贪心算法的思想,每次选择时都做出贪心选择。在迪科斯彻算法中就是使用了上面的原理进行求解的。具体的介绍可以wiki一下:http://zh.wikipedia.org/wiki/Dijkstra算法.里面已经包含了伪代码。下面是Java版的实现代码,需要注意的是这里没有使用伪代码中的优先队列,而是使用一个布尔类型的标记数组来通过标记来模拟优先队列的"出队列"。
package com.wly.algorithmbase.search;
/**
* 迪科斯彻算法
* 基于广度优先搜索,使用优先队列存储检索信息
* 伪代码:
1 function Dijkstra(G, w, s)
2 for each vertex v in V[G] // 初始化
3 d[v] := infinity // 將各點的已知最短距離先設成無窮大
4 previous[v] := undefined // 各点的已知最短路径上的前趋都未知
// 因为出发点到出发点间不需移动任何距离,所以可以直接将s到s的最小距离设为0
5 d[s] := 0
6 S := empty set
7 Q := set of all vertices
8 while Q is not an empty set // Dijkstra演算法主體
9 u := Extract_Min(Q)
10 S.append(u)
11 for each edge outgoing from u as (u,v)
12 if d[v] > d[u] + w(u,v) // 拓展边(u,v)。w(u,v)为从u到v的路径长度。
13 d[v] := d[u] + w(u,v)// 更新路径长度到更小的那个和值。
14 previous[v] := u // 紀錄前趨頂點
* @author wly
*
*/
public class DijstraAlgorithm {
private static int IMAX = 10000; //不连通状态
public static int[][] adjMat = {
{0,10,3,IMAX},
{IMAX,0,4,5},
{IMAX,4,0,10},
{IMAX,IMAX,IMAX,0}
};
public static void main(String[] args) {
DijstraAlgorithm dijstraAlgorithm = new DijstraAlgorithm();
int start = 2;
int end = 3;
System.out.println("------测试------");
System.out.println("\n从" + start + "到" + end
+ "的距离是:" + dijstraAlgorithm.reslove(adjMat, start, end));
System.out.println("------测试------");
start = 0;
end = 3;
System.out.println("\n从" + start + "到" + end
+ "的距离是:" + dijstraAlgorithm.reslove(adjMat, start, end));
}
/**
* 在用邻接矩阵adjMat表示的图中,求解从点s到点t的最短路径
* @param adjMat 邻接矩阵
* @param s 起点
* @param t 终点
* @return
*/
public int reslove(int[][] adjMat,int s,int t) {
//判断参数是否正确
if(s < 0 || t < 0 || s >=adjMat.length || t >= adjMat.length) {
System.out.println("错误,顶点不在图中!");
return IMAX;
}
//用来记录某个顶点是否已经完成遍历,即替代优先队列的"移出队列"动作
boolean[] isVisited = new boolean[adjMat.length];
//用于存储从s到各个点之间的最短路径长度
int[] d = new int[adjMat.length];
//初始化数据
for(int i=0;i<adjMat.length;i++) {
isVisited[i] = false;
d[i] = IMAX;
}
d[s] = 0; //s到s的距离是0
isVisited[s] = true; //将s标记为已访问过的
//尚未遍历的顶点数目,替代优先队列是否为空的判断即Queue.isEmpty()
int unVisitedNum = adjMat.length;
//用于表示当前所保存的子路径中权重最小的顶点的索引,对应优先队列中,默认是起点
int index = s;
while(unVisitedNum > 0 && index != t) {
int min = IMAX;
for(int i=0;i<adjMat.length;i++) { //取到第i行的最小元素的索引
if(min > d[i] && !isVisited[i]) {
min = d[i];
index = i;
}
}
if(index == t || unVisitedNum == 0) {
System.out.print(index); //打印最短路径
} else {
System.out.print(index + "=>"); //打印最短路径
}
for(int i=0;i<adjMat.length;i++) {
if(d[index] + adjMat[index][i] < d[i]) {
d[i] = d[index] + adjMat[index][i];
}
}
unVisitedNum --;
isVisited[index] = true;
}
return d[t];
}
}
运行效果:
------测试------
2=>1=>3
从2到3的距离是:9
------测试------
0=>2=>1=>3
从0到3的距离是:12
对应的图结构:
O啦~~~
装载请保留出处:http://blog.csdn.net/u011638883/article/details/17200869
谢谢!!