正文

最短路径算法2007-03-21 09:10:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/lingdlz/24154.html

分享到:

利用 迪积斯特拉 算法求 " 有向图 " 中某点到其余各点的最短路径  
并输出从该点到各点的详细路径,以及总权值。这个程序上学期就写了
今天偶然发现有两个错误,查了我将近两个小时,一个是不可达点的
输出不明显,最大的错误是重复释放了一个指针,我以为是算法错了
从头查到尾,增加了详细的注释,这或者会影响阅读代码,的确,过
多的注释会让代码阅读者不能真正理解代码,当然这也要代码可读性
高。是的代码应该强调,可读性,简洁性,其次才是高效性。

输入: 首先输入图的顶点数 n 边数 m        
      接着下一行输入源点 sourcePoint       
      然后输入每一条边的数据包括 起点s,终点e,权值v   
           包括起点,终点,权值 (顶点从 1 开始编号)    
输出: 输出到各点的详细路径以及权值       
事例: (建议用管道测试)          
输入文件 data.txt  内容如下:       
7 12             
3             
1 2 3             
2 6 7             
6 5 9            
5 4 2        
1 4 3            
1 3 6         
3 6 1         
3 5 5         
6 7 1         
1 7 2         
4 7 10         
5 7 5           
输出:         
The shortest path as followed :
From 3 can't to 1 !
From 3 can't to 2 !
From 3 to 4: 3-5-4 total value is : 7
From 3 to 5: 3-5 total value is : 5
From 3 to 6: 3-6 total value is : 1
From 3 to 7: 3-6-7 total value is : 2
Press any key to continue

编译环境:VC ++ 6.0            
Author  :   江南孤峰 
Time :2007--3--21           


#include <stdio.h>
#include <process.h>
#include <stdlib.h>
#include <limits.h>
#include <malloc.h>
#include <string.h>

typedef struct Side{// 路径中的节点
 int point; // 节点编号
 struct Side *next;
}DefSide;

typedef struct Result{// 最短路径属性
 int flag; // 标记
 int start;  // 路径的起始点,(除源点)
 int totalVaule; // 整条路径的总权值
 DefSide *thead; // 路径经过的各个节点
}DefResult;

int main(){
 int  sourcePoint;
 int  nNode,nSide,s,e,v,i,j;
 int  *meter,nflag;
 DefResult *presult;
 DefSide  *temp,*temp2;

 scanf("%d %d",&nNode,&nSide);
 scanf("%d",&sourcePoint);

 // 用链表存储最短路径,共有(nNode-1)条路径,因为下标从1开始
 presult = (DefResult *)malloc(sizeof(DefResult) * nNode);

 // 分配对应大小的矩阵,为便于理解,行列下标都从1开始
 meter=(int*)malloc(sizeof(int)*(nNode+1)*(nNode+1));
 memset(meter,0,sizeof(int)*(nNode+1)*(nNode+1));

 for(i = 1; i <= nSide; i ++){
  scanf("%d %d %d",&s,&e,&v); 
  *(meter + s * nNode + e) = v;
 }

    // 初始化从源点到各点的最短路径,并求出与源点直接连接权值最小的点
 for(i = 1,v = INT_MAX; i <= nNode; i ++){
  // 标记从源点到对应点的最短路径未求出
  presult[i].flag = 0; 
  // 路径初始化为空
  presult[i].thead = NULL;
  // 从源点到该点没有直接连接
  if( !*(meter + sourcePoint*nNode + i) ){
   // 路径没有起始点(除源点),设值为 -1
   presult[i].start = -1;
   // 路径长度初始化为最大: INT_MAX
   presult[i].totalVaule = INT_MAX;
   continue;
  }
  //  从源点到该点有直接连接,路径长度初始化为源点到该点的权值
  presult[i].totalVaule = *(meter + sourcePoint*nNode + i);
  //  路径从该点开始(除源点)
  presult[i].start = i;
  // 求出与源点直接连接权值最小的点,权值存于 v 中,点编号存于 s 中
  if(v > *(meter + sourcePoint*nNode + i)){
   v = *(meter + sourcePoint*nNode + i);
   s = i;
  }
 }
 // 标记该点不必考虑了,值为 0
 *(meter + sourcePoint*nNode + s) = 0;
 // 标记从源点到该点的最短路径已经找到
 presult[s].flag = 1; 
 //源点到源点也标记完成
 presult[sourcePoint].flag = 1;

 // 从源点到 n 个顶点的最短路径是否求完,有两个点已经完成即
 // 源点和与源点直接邻接并且权值最小的点,nflag 初始化为 2
 for(nflag = 2; nflag <= nNode; nflag ++){
  // s是目前源点到其它点最短路径的结束点
  v = presult[s].totalVaule;
  // 扫描从 s  出发到其他各点的权值,以决定是否更新邻接表和路径链表
  for(i = 1; i <= nNode; i ++){
   if(*(meter + s*nNode + i) &&
    (v + *(meter + s*nNode + i) < presult[i].totalVaule)){
    presult[i].totalVaule = v + *(meter + s*nNode + i);
    presult[i].start = presult[s].start;
    // 更新从源点到点 i 的路径
    while(presult[i].thead){
     temp = presult[i].thead;
     presult[i].thead = temp -> next;
     free(temp);
    }
    if(presult[s].thead){
     temp2 = presult[i].thead = (DefSide*)malloc(sizeof(DefSide));
     presult[i].thead->point= presult[s].thead->point;
     temp = presult[s].thead;
     while(temp->next){
      temp = temp -> next;
      temp2 = temp2->next = (DefSide*)malloc(sizeof(DefSide));
      temp2->point = temp->point;
     }
     temp2 = temp2->next = (DefSide*)malloc(sizeof(DefSide));
     temp2->point = i;
     temp2->next = NULL;
    }
    else{
     presult[i].thead  = (DefSide*)malloc(sizeof(DefSide));
     presult[i].thead->point = i;
     presult[i].thead->next = NULL;
    }
   }
  }
  // 筛选目前结果中的最短路径
  for(j = 1,v = INT_MAX; j <= nNode; j ++){ 
   if(!presult[j].flag && presult[j].totalVaule
        && presult[j].totalVaule < v){
    v = presult[j].totalVaule;
    s = j;
   }
  }
  // 标记从源点到 s 点的最短路径已经找到
  presult[s].flag = 1;
  *(meter + sourcePoint*nNode + s) = 0;
 }

 printf("The shortest path as followed :\n");
 for(i = 1; i <= nNode; i ++){
  if(i == sourcePoint)
   continue;
  if(presult[i].start == -1){
   printf("From %d can't to %d !\n",sourcePoint,i);
   continue;
  }
  printf("From %d to %d: %d-%d",sourcePoint,i,sourcePoint,presult[i].start);
  temp = presult[i].thead;
  while(temp){
   printf("-%d",temp -> point);
   temp2 = temp;
   temp = temp -> next;
   free(temp2);
  }
  printf(" total value is : %d\n",presult[i].totalVaule);
 }
 free(meter);
 return EXIT_SUCCESS;
}
 

阅读(5492) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册