整理 Dijkstra算法

Dijkstra算法是解单源最短路径问题的一个贪心算法。
其基本思想是:设置顶点集合S并不断地做贪心选择来扩充这个集合。一个顶点属于S当且仅当从源到该顶点的最短路径长度已知。
初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路径称为从源到u的特殊路径,并且用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist做出必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其他顶点之间的最短路径长度。
Dijkstra算法可描述如下,其中输入的带权的有向图G=(V,E),V={1,2,…,n},顶点v是源。c是一个二维数组,c[ i ][ j ]表示边(i,j)不属于E时,c[ i ][ j ]是一个大数。disk[i]表示当前从源到顶点i的最短特殊路径长度


当然我们可以根据上述算法思想用二维数组写出最简单的Dijkstra算法

[cpp] 
view plain
copy

  1. void Dijkstra(int n,int v, type dist[], int prev[],type **c)  
  2. {  
  3.     //s[i]为true,则顶点         ; s[i]为true,则顶点  
  4.     bool s[n+1];  
  5.     // 初始化,其中顶点1为源  
  6.     for(int i=1;i<=n;i++)  
  7.     {  
  8.         dist[i]=c[v][i];  
  9.         s[i]=false;  
  10.         if(dist[i]==maxint)  prev[i]=0;  // 没有路直接到源  
  11.         else   prev[i]=1        //有路直接到源  
  12.     }  
  13.     disk[v]=0;  
  14.     s[v]=true;    // 起始时,只有源属于集合S  
  15.   
  16.     //将其余n-1个顶点添加到集合S中,每次循环添加一个顶点到S中  
  17.     for(int i=1;i<n;i++)  
  18.     {  
  19.         // 从V-S中取出具有最短路径长度的顶点u,将u添加到S中  
  20.         int temp=maxint;  int u=1;  
  21.         for(int j=1; j<=n; j++)  
  22.             if((!s[j])&&(dis[j]<temp))   
  23.             {  
  24.                 u=j;   
  25.                 temp=dist[j];  
  26.             }  
  27.             s[u]=true;  
  28.   
  29.             //在S中添加顶点u后,对数组dist做必要的修改  
  30.             for(int j=2; j<=n; j++)  
  31.                 if((!s[j])&&(c[u][j]<maxint))   
  32.                 {  
  33.                     type newdist=dist[u]+c[u][j];  
  34.                     if(newdist<dist[j]  
  35.                     {  
  36.                         dist[j]=newdist;  
  37.                         prev[j]=u;  
  38.                     }  
  39.                 }  
  40.     }  
  41. }  

在很多情况下,点会有很多,但是边却没有那么多,这样的话,二维数组中就会有很多没有被利用,这不仅浪费内存,而且速度也会受到一定的影响。在这种情况下,我们就可以采用邻接矩阵或者heap 或者是优先队列来优化Dijkstra算法:
下面给出它的优先队列优化Dijkstra算法



[cpp] 
view plain
copy

  1. #include<vector>  
  2. #include<queue>  
  3.   
  4. struct Edge  
  5. {  
  6.     int from ;  
  7.     int to;  
  8.     int dist;  
  9.   
  10. };  
  11.   
  12. //Dijkstra算法用到优先队列的结点  
  13. struct HeapNode  
  14. {  
  15.     int d,u;  
  16.     bool operator < (const HeapNode& rhs) const   
  17.     {  
  18.         return d > rhs.d;  
  19.     }  
  20. };  
  21.   
  22. struct Dijkstra  
  23. {  
  24.     int n;  
  25.     long m;//点数和边数  
  26.     vector<Edge> edges;//边列表  
  27.     vector<int> G[MAX];//每个结点出发的边编号(从0 开始编号)  
  28.     bool done[MAX];//是否已永久标号  
  29.     int d[MAX]; //s到各个点的距离  
  30.     int p[MAX];//最短路中的上一条边  
  31.   
  32.     void init(int n)  
  33.     {  
  34.         this->n = n;  
  35.         for(int i = 0 ; i < n ;i++)  
  36.             G[i].clear();//清空邻接表  
  37.         edges.clear();//清空边表  
  38.     }  
  39.   
  40.     void AddEdge(int from,int to,int dist)  
  41.     {  
  42.         //如果是无向图,每条边需调用两次AddEdge  
  43.         Edge e;  
  44.         e.from = from ;  
  45.         e.to = to;  
  46.         e.dist = dist;  
  47.         edges.push_back(e);  
  48.         int mm = edges.size();  
  49.         G[from].push_back(mm-1);  
  50.     }  
  51.   
  52.     void dijkstra(int s)  
  53.     {  
  54.         //求s到所有点的距离  
  55.         priority_queue<HeapNode> Q;  
  56.         for(int i=0;i<n;i++)  
  57.             d[i]=INT_MAX;  
  58.         d[s]=0;  
  59.         memset(done,0,sizeof(done));  
  60.   
  61.         HeapNode h0;  
  62.         h0.d=0;  
  63.         h0.u=s;  
  64.         Q.push(h0);  
  65.         while(!Q.empty())  
  66.         {  
  67.             HeapNode x = Q.top();  
  68.             Q.pop();  
  69.   
  70.             int u = x.u;  
  71.             if(done[u])  
  72.                 continue;  
  73.   
  74.             done[u] = true;  
  75.             for(int i=0;i<G[u].size();i++)  
  76.             {  
  77.                 Edge& e = edges[G[u][i]];  
  78.                 if(d[e.to] > d[u] + e.dist)  
  79.                 {  
  80.                     d[e.to] = d[u] + e.dist;  
  81.                     p[e.to] = G[u][i];  
  82.                     HeapNode h;  
  83.                     h.d = d[e.to];  
  84.                     h.u = e.to;  
  85.                     Q.push(h);  
  86.                 }  
  87.             }  
  88.         }  
  89.     }  
  90. };  
    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/a237653639/article/details/21211547
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞