最短路径的实现

最短路径:一个源点到图中每个顶点的距离。在实现这个的时候,构建的是一个有向图。我们先看看算法的大致思想:
(1)带权邻接矩阵arcs来表示带权有向图,若<vi,vj>不存在,则置其权值为最大值。
(2)选择vj,使得D[j] = Min{D[i],该元素未加入最短路径集合}
(3)修改从v出发到那个未处理集合的顶点的最短路径。D[j] + arcs[j][k] < D[k].更新这个距离,直至最短距离不发更新。
我在实现这个的时候,遇到一些细节问题:在这个图中可能存在不可达点,所以有时可以提前结束最短路径的算法,在更新路径的时候,你会发现当更新一个不可达点时,会出现负数,这就是计算机的数据溢出造成的,所以在处理的时候,需要在更新的时候过滤掉不可达点。
#include "graph.h"
#include <stdio.h>


//#define DEBUG


/*********************************************/
/*          最短路径算法                     */
/*          参数:G  开始点                  */
/*          功能                           */
/*********************************************/
void ShortestPath_DIJ(const MGraph *g,const int v0)
{
int closedge[MAX_VERTEX_NUM];          //存储v0到每个节点的最短路径权值 
    bool colored[MAX_VERTEX_NUM];           //标记该节点是否处理过 
int i;
//得到起始点邻接的点权值
    //不邻接的都是最大值 
for(i=0;i<g->vexnum;i++)                
{
closedge[i] = g->arcs[v0][i];
colored[i]  = false;
}
#ifdef DEBUG
  for(i=0;i<g->vexnum;i++)
      printf("%d ",closedge[i]);
   printf("\n");
#endif
//值为0表明该点已加入树 
closedge[v0] = 0;
colored[v0]  = true;

//逐渐构建最短路,每次加入一个点 
//注意存在不可达点。。 
int vtemp = -1;
while(v0 != vtemp)
{
      int temp = INT_MAX;        //记录最小权值 
      vtemp = v0;             //记录将加入点
            //查找到最小权值点 
        for(i=0;i<g->vexnum;i++)
{
if((!colored[i])&&(temp > closedge[i]))
{
temp = closedge[i];
vtemp = i;
}
}
//   printf("The node[%d]:%d\n",vtemp,temp);
//由于加入新节点,所以改变每个节点到v0的值 
  for(i=0;i<g->vexnum;i++)
{
            if(g->arcs[vtemp][i] != INT_MAX)            //过滤不可达点     
 if(closedge[i] > (closedge[vtemp] + g->arcs[vtemp][i]))
{
closedge[i] = g->arcs[vtemp][i] + closedge[vtemp];
}
}
    colored[vtemp] = true;           //设置为加入点 
    #ifdef DEBUG
      for(i=0;i<g->vexnum;i++)
          printf("%d ",closedge[i]);
      printf("\n");
   #endif
}
for(i=0;i<g->vexnum;i++)
  printf("%d ",closedge[i]);
printf("\n");
}
/*test
6 8
0 1 2 3 4 5END
0 2 10
0 4 30
0 5 100
1 2 5
2 3 50
3 5 10
4 3 20
4 5 60
end*/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值