Dijkstra算法

原文地址:http://blog.csdn.net/stanfordzhang/article/details/6626584


1. Dijkstra's Algorithm是解决单源最短路径问题,即:从某个源点到其余各顶点的最短路径;

2. Dijkstra's Algorithm中有两上关键点要注意(这是我学习的时候不仔细,导致走了很多弯路)。这里先明确两个集合:所有顶点集V和已选中顶点集S。

    一、找到当前未选中点(V - S)中距离源点最近的点;

    二、更新未选中点到源点的距离。

3. 建议:结合程序及一个示例来理解这个算法。我在学习时,看别人画的各种表格来描述这个算法,看了半天,感觉是明白了,但常常发现有不明确的地方。在结合程序理解算法之后,则有豁然开朗之感。

    下图来自《Introduction of Algorithm》中的示例,这个示例个人觉得很典型,如下图:

程序如下(来自《数据结构(C语言版)》——严蔚敏):

 

[cpp]  view plain copy
  1. void ShortestPath_Dijkstra(size_t** arcs, size_t v0, bool** P, size_t* D, size_t vexnum)  
  2. {  
  3.     size_t i = 0;  
  4.     size_t v = 0;  
  5.     size_t w = 0;  
  6.     size_t min = 0;  
  7.     //用Dijkstra算法求有向网的v0顶点到其余顶点v的最短路径P[v]及其带权长度D[v]。  
  8.     //P[v][w]为true,则w是从v0到v当前求得最短路径上的顶点。  
  9.     //final[v]为true,当且仅当v属于S时,即已经求得从v0到v的最短路径。  
  10.     bool* final = new bool[vexnum];  
  11.     for (v = 0; v < vexnum; v++)  
  12.     {  
  13.         //初始化  
  14.         final[v] = false;  
  15.         D[v] = arcs[v0][v];  
  16.         for (w = 0; w <vexnum; w++)  
  17.         {  
  18.             P[v][w] = false// 设置空路径  
  19.         }  
  20.         //P[v][w]为true,则w是从v0到v当前求得最短路径上的顶点。  
  21.         //在这里初始化,说明v0到v的路径上可通,则v0和v点都在最短路径的点上。  
  22.         if (D[v] < INFINITY)  
  23.         {  
  24.             P[v][v0] = true;  
  25.             P[v][v] = true;  
  26.         }  
  27.     }  
  28.     //初始化,v0顶点属于S集  
  29.     D[v0] = 0;  
  30.     final[v0] = true;  
  31.     //开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集  
  32.     for (i = 1; i < vexnum; i++) // 其余vexnum - 1个点  
  33.     {  
  34.          min = INFINITY; // 当前所知离v0顶点的最近距离  
  35.          //注意:这个循环用来找到距离v0最近的点  
  36.          for (w = 0; w < vexnum; w++)   
  37.          {  
  38.              if (!final[w]) // w顶点在V - S中  
  39.              {  
  40.                  //w顶点离v0顶点更近  
  41.                  if (D[w] < min)  
  42.                  {  
  43.                      v = w;  
  44.                      min = D[w];  
  45.                  }  
  46.              }  
  47.          }  
  48.          //找到之后,将v放入S中  
  49.          final[v] = true;  
  50.          //更新当前最短路径及距离  
  51.          for (w = 0; w < vexnum; w++)  
  52.          {  
  53.              //修改D[w]和P[w],w属于V - S  
  54.              //当前找到的点是v,更新v到V - S中的点的距离,因为有时D[w]中的距离不是直连的  
  55.              if (!final[w] && (min + arcs[v][w] < D[w]))  
  56.              {  
  57.                  D[w] = min + arcs[v][w];  
  58.                  //P[w] = P[v];  
  59.                  //P为一个二维矩阵,每一行代表到这一行所代表结点的最短路径,行标代表结点下标。  
  60.                  //因为P[v][w]为true,则w是从v0到v当前求得最短路径上的顶点,此时v是当前找到的点,  
  61.                  //将P[v]复制到P[w]中,并且将P[w][w]设置为true,也就是在点v的基础上加点w。  
  62.                  memcpy(P[w], P[v], vexnum);  
  63.                  P[w][w] = true;  
  64.              }  
  65.          }  
  66.     }  
  67. }  
360图书馆搬来了一个java版本:http://www.360doc.com/content/08/0918/22/73664_1655859.shtml

public class Dijkstra {   
     public static void main(String[] args) {       
     new Dijkstra().use();    
}      
  public void use(){    
        new Dijkstra().dijkstra(0, a, dist, prev);      
          for (int i = 0; i < dist.length; i++) {     
               System.out.print(dist[i]+"  ");     
   }   
 }  
  //单元最短路径问题的Dijkstra算法    
public void dijkstra(int v ,float[][] a, float[] dist,int[] prev){   
     int n = dist.length - 1 ;     
     if(v < 0 || v > n-1)  return;     
     boolean[] s = new boolean[n+1];     
           //初始化      
     for(int i = 1; i <= n; i++){   
         dist[i] = a[v][i];       
         s[i] = false;        
        if(dist[i] == Float.MAX_VALUE){        
            prev[i] = 0;        
           } else {            
                prev[i] = v;         
           }   
     }         
   dist[v] = 0;       
   s[v] = true;     
   for(int i = 1; i < n; i++){       
     float temp = Float.MAX_VALUE;    
        int u = v;      
       for(int j = 1; j <= n; j++){    
            if((!s[j]) && (dist[j] < temp)){        
                  u = j;               
                 temp = dist[j];         
               }      
      }         
   s[u] = true;  //找到了第一个并入S的节点   
    for(int j = 1; j <= n; j++){       
        if((!s[j]) && (a[u][j] < Float.MAX_VALUE)){     
               float newdist = dist[u] + a[u][j];        
               if(newdist < dist[j]){                 
                  //dist[j] 减少                 
                   dist[j] = newdist;     
                   prev[j] = u;                
                    }       
         }         
   }      
  }    
}    

private   float[][] a = {   
              {0,10,max,30,100},    
                {max,0,50,max,max},   
                 {max,max,0,max,10},     
              {max,max,20,0,60},          
              {max,max,max,max,0}         
           };      
 private float[] dist = new float[5];   
 private  int[] prev = new int[5];    
 public static final float max = Float.MAX_VALUE;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值