dijkstra算法

来源:互联网 发布:远景能源怎么样 知乎 编辑:程序博客网 时间:2024/06/08 16:08

1.dijkstra算法简介

Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它应用了贪心算法模式,是目前公认的最好的求解最短路径的方法。算法解决的是有向图中单个源点到其他顶点的最短路径问题,其主要特点是每次迭代时选择的下一个顶点是标记点之外距离源点最近的顶点。但由于dijkstra算法主要计算从源点到其他所有点的最短路径,所以算法的效率较低。

2.dijkstra算法基本过程

假设路网中每一个节点都有标号 是从出发点s到点t的最短路径长度;表示从s到t的最短路径中t点的前一个点。求解从出发点s到点t的最短路径算法的基本过程为:

1.      初始化。出发点设置为:

 

标记起源点s,记k = s,其他所有点设为未标记。

2.      检验从所有已标记的点k到其他直接连接的未标记的点j的距离,并设置:


3.      选取下一个点。从所有未标记的点中选取 最小的点i,点i被选为最短路径中的一点,并设为已标记的。

4.      找到点i的前一点。从已经标记的点集合中找到直接连接到点i的点,并标记为 。

5.      标记点i。如果所有的点已标记,则算法结束。否则,记k = i,转到2继续。

从以上算法的步骤中可以看出 :dijkstra算法的关键部分是从未标记的点中不断地找出距离源点距离最近的点,并把改点加入到标记的点集合中,同时更新未标记的点集合中其余点到起始点的最短估计距离[z1] 。

以一个带有权值的无向图为例,用dijkstra算法分析从源点A到目标点F的最短路径。


1. 用带有权值的一个矩阵w表示含有n各节点的带权无向图, 代表弧段 的权值,如果从节点 到节点 不连通,那么 ,带权值图邻接矩阵如下图所示.设置A为源点,G为目的点, 代表从节点A到有向图中其他节点 的最短路径长度。设置初始值 代表标记的节点集合。


2. 是从A点出发求出的一条最短路径上的终止节点,令 ;


3.  修改起始节点A到集合之间的最短路径的长度值,如果d(j)+w(j,k) < d(k),那么d(k) = d(j) + w(j,k);

4. 重复步骤2、3的操作N-1次,最终得到从起始节点A到其他节点的最短路径,按照递增的顺序排列路径的长度。

3.dijkstra算法的流程图如下所示:

实现代码:java版


package com.zdt.impl;


public class Dijkstral { 
private static int M = 10000; //此路不通 
public static void main(String[] args) 

int[][] weight1 = {
//邻接矩阵         
{0,3,2000,7,M},         
{3,0,4,2,M},         
{M,4,0,5,4},        
{7,2,5,0,6},           
{M,M,4,6,0}     };     
int[][] weight2 = {         
{0,10,M,30,100},         
{M,0,50,M,M},         
{M,M,0,M,10},         
{M,M,20,0,60},         
{M,M,M,M,0}     };         
int start=0;     
int[] shortPath = dijkstra(weight2,start);           
for(int i = 0;i < shortPath.length;i++)        
System.out.println("从"+start+"出发到"+i+"的最短距离为:"+shortPath[i]); 
}   
public static int[] dijkstra(int[][] weight, int start) { 
//接受一个有向图的权重矩阵,和一个起点编号start(从0编号,顶点存在数组中)   
//返回一个int[] 数组,表示从start到它的最短路径长度  
int n = weight.length;      //顶点个数 
//System.out.print(n);
int[] shortPath = new int[n];  //保存start到其他各点的最短路径
String[] path = new String[n]; //保存start到其他各点最短路径的字符串表示
for(int i=0;i<n;i++)   
path[i]=new String(start+"-->"+i); 
int[] visited = new int[n];   //标记当前该顶点的最短路径是否已经求出,1表示已求出    
//初始化,第一个顶点已经求出 
shortPath[start] = 0; visited[start] = 1;

for(int count = 1; count < n; count++) {   
//要加入n-1个顶点  
int k = -1;        
//选出一个距离初始顶点start最近的未标记顶点  
int dmin = Integer.MAX_VALUE; 
//System.out.print(dmin);
for(int i = 0; i < n; i++) 
{  
if(visited[i] == 0 && weight[start][i] < dmin) 
{   
dmin = weight[start][i];  
k = i;  

}     
//将新选出的顶点标记为已求出最短路径,且到start的最短路径就是dmin  
shortPath[k] = dmin;  
visited[k] = 1;     
//以k为中间点,修正从start到未访问各点的距离   
for(int i = 0; i < n; i++) {
if(visited[i] == 0 && weight[start][k] + weight[k][i] < weight[start][i]) 
{   
weight[start][i] = weight[start][k] + weight[k][i];  
   path[i] = path[k] + "-->" + i;   
}  

}



for(int i = 0; i < n; i++) 
{  
System.out.println("从"+start+"出发到"+i+"的最短路径为:"+path[i]); }
   System.out.println("=====================================");  
   return shortPath; 
}


}


1 0
原创粉丝点击