最短路径(Dijkstra)

有一幅无向图图


对应的邻接矩阵
char *vertexArray[8] = {"a", "v1", "v2", "v3", "v4", "v5", "v6", "b"};
int undiGraph[8][8] = {
          //a,v1,v2,v3,v4,v5,v6, b
      //a  {X, 2, 8, 1, X, X, X, X},   //1+7+2+6
      //v1 {2, X, 6, X, 1, X, X, X},
      //v2 {8, 6, X, 7, 4, 2, 2, X},
      //v3 {1, X, 7, X, X, X, 9, X},
      //v4 {X, 1, 4, X, X, 3, X, 9},
      //v5 {X, X, 2, X, 3, X, 4, 6},
      //v6 {X, X, 2, 9, X, 4, X, 2},
      //b  {X, X, X, X, 9, 6, 2, X}
};

求从a到b的最短路径?


(使用“迪杰斯特拉算法”)解题过程:
1.先将“源顶点a”作为“轴心点”开始遍历所有可以抵达的“结点v1, v2, v3”,记录到达“结点v1, v2, v3”的路径值到对应的shortestPathsV[8] = {X(done), 2, 8, 1, X, X, X, X};
并且将“轴心点a”标记在flagV[8] = {1,0,0,0,0,0,0,0},标记为1后续不再使用此轴心点。
(注意:shortestPathsV[8]和flagV[8]每一项对应一个结点)


2.从shortestPathsV[8]中选择当前最短路径值"结点v3",遍历v3所有可以抵达的“结点v2, v6”,记录到达“v2, v6”的“路径值的和”到对应的shortestPathsV[8] = {X, 2, 8, 1(done), X, X, 1+9, X};
将“轴心点v3”标记在flagV[8] = {1,0,0,1,0,0,0,0}。
(注意:shortestPathsV[]只取到达该结点的最短路径值(之前取的较小值将被取代),与之前记录相等的值(v2)不改变))


3.从shortestPathsV[8]中选择当前最短路径值"结点v1"(排除a, v3),遍历v1所有可以抵达的“结点v2, v4”,记录到达“结点v2, v4”的“路径值的和”到对应的shortestPathsV[8] = {X, 2(done), 8, 1(done), 2+1, X, 1+9, X};
将“轴心点v3”标记在flagV[8] = {1,1,0,1,0,0,0,0}。


4.(排除a, v3, v1),从shortestPathsV[8]中选择当前最短路径值"结点v4", 遍历v4所有可以抵达的“结点v2, v5, b”,记录到达“结点v2, v5, b”的“路径值的和”到对应的shortestPathsV[8] = {X, 2(done), 2+1+4(替换8), 1(done), 3(done), 2+1+3, 1+9, 2+1+9};
将“轴心点v4”标记在flagV[8] = {1,1,0,1,1,0,0,0}。


5.(重复上述,遍历,更新shortestPathsV[8]和flagV[8])
选中v5,更新
shortestPathsV[8] = {X(done), 2(done), 7, 1(done), 3(done), 6(done), 10, 12}; //没有更新
将“轴心点v5”标记在flagV[8] = {1,1,0,1,1,1,0,0},
选中v2,更新
shortestPathsV[8] = {X(done), 2(done), 7(done), 1(done), 3(done), 6(done), 9, 12}; //更新到达6的值
将“轴心点v2”标记在flagV[8] = {1,1,1,1,1,1,0,0},
 
6.只剩下v6(除去b),更新v6可以抵达的值
shortestPathsV[8] = {X(done), 2(done), 7(done), 1(done), 3(done), 6(done), 9(done), 11};
将“轴心点v5”标记在flagV[8] = {1,1,1,1,1,1,1,0},
 
7.最后,只剩下终点值b(b已经在遍历的过程中被更新为最小值),即取得最小路径值11


#include <stdio.h>
#include<iostream.h>

#define N 8 //number of vertex
#define X 0XFFFF  //no path
#define DONE 1  //traversed
#define UNDONE 0  

int dijkstraAlg(int num, int undiGraph[][N], int startV, int endV, int preV[])
{
    int shortestPathsV[num]; //shortestPathsV[num]表示从"源顶点"到"顶点num"的最短路径长度
    bool flagV[num];  //flagV[num]标记"顶点num"是否(即将)作为轴点遍历;DONE表示被选中(即将)遍历。同时也表示已经求得到达该结点的最短路径。

    int minWeight = X; //中间值,“当前最短路径值”;始终从“当前最短路径值”开始遍历
    int minId;//“当前最短路径值”结点的ID
	
    int tmpWeight = 0; //临时值,“当前路价值”;和pathsV[num]比较,如果小,则更新pathsV[num](为最短路径)
	
    //初始化
    for (int i=0; i<num; i++)
    {
        flagV[i] = UNDONE; //全部初始化未遍历
        shortestPathsV[i] = undiGraph[startV][i]; //初始化"源顶点"能够到达的最短路径值(即undiGraph第1列的所有数据(也是第一行的所有数据))
        preV[i] = -1;  //途经结点数组
        preV[i] = (undiGraph[startV][i] != X) ? startV : -1;
    }

    // shortestPathsV[startV] = -1; //起点标记为-1 不被更新
    flagV[startV] = DONE; //标记"源顶点",表示已经求得到达该结点的最短路径

   for (int i=1; i<num; i++) //还需要遍历n-1个顶点
   {
       minWeight = X;
       //寻找下一个待加入的顶点(选轴心点)
       for (int j=0; j<num; j++)
       {
           if (flagV[j]!=DONE && shortestPathsV[j]<minWeight)
           {
               minWeight = shortestPathsV[j];   //始终选择最小路径值和最小路径值对应的顶点	
               minId = j;
           }
       }
	   cout<<"i = "<<i<<" minId = "<<minId<<endl;
       flagV[minId] = DONE; //flagV[minId] 值为DONE,后续不再选该数据

       if (minId == endV) //最后一个结点已加入
       {
           return shortestPathsV[endV];
       }

       //选中轴点后,依次遍历该轴点可抵达的路径;
       //在下面使用了遍历数组第二维的方式。
       for (int j=0; j<num; j++) 
       {
           if (minWeight==X || undiGraph[minId][j]==X)  //遍历数组第二维		                                                
               continue;
           tmpWeight = minWeight + undiGraph[minId][j]; //当前轴点可抵达路径值
           if(j!=startV && tmpWeight<shortestPathsV[j]) //起点无须更新;比较已经存档的路径值
           {
               shortestPathsV[j] = tmpWeight;  //当前能够到达的最小路径值,替换之前保存的值
               preV[j] = minId; //记录到达最小路径值的结点(ID)到preV中						
           }
	    cout<<"shortestPathsV["<<j<<"] = "<< shortestPathsV[j]<< "  ";	
        cout<<"minId = "<<minId<<" ";		  
	    cout<<"preV["<<j<<"] = "<< preV[j]<<endl;				  
       }
   }
}   

//print path
void printShortestPath(int num, int undiGraph[][N], int startV, int endV, const char **vertexArray)
{
    int preV[num];//到达最小路径值的结点(ID),保存轴心结点
    int shortestPath = dijkstraAlg(num, undiGraph, startV, endV, preV);
		
    printf("the shortest path is: %d  ", shortestPath);

    int tmpPathsV = endV;
    do
    {
      printf("%s <--- ", vertexArray[tmpPathsV]);//这里的用法很绕
	  tmpPathsV = preV[tmpPathsV];
    }while(tmpPathsV != startV);
    printf("%s\num", vertexArray[startV]);

}

//undirected graph
int main()
{
    const char *vertexArray[N] = {"a", "v1", "v2", "v3", "v4", "v5", "v6", "b"};
    int undiGraph[N][N] = {
	         //a,v1,v2,v3,v4,v5,v6, b
    /*a*/     {X, 2, 8, 1, X, X, X, X},   //1+7+2+6
    /*v1*/    {2, X, 6, X, 1, X, X, X},
    /*v2*/    {8, 6, X, 7, 4, 2, 2, X},
    /*v3*/    {1, X, 7, X, X, X, 9, X},
    /*v4*/    {X, 1, 4, X, X, 3, X, 9},
    /*v5*/    {X, X, 2, X, 3, X, 4, 6},
    /*v6*/    {X, X, 2, 9, X, 4, X, 2},
    /*b*/     {X, X, X, X, 9, 6, 2, X}
    };
		
   printShortestPath(N, undiGraph, 0, 7, vertexArray);

   return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值