Dijkstra算法实现--铁路网出行规划

铁路交通网的最短路径

在有向图表示的铁路网中,利用Dijkstra算法,求出从指定的起点城市到终点城市的最短路径,并输出。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define LISTINITSIZE 20
#define INF __DBL_MAX__ //双精度浮点数最大值
typedef int Status;
typedef char *VertexType;//顶点信息类型(城市名)
typedef struct ArcNode{ //邻接表的一条边
    int adjvex;
    struct ArcNode *nextarc;
    double weight;      //边权
}ArcNode;
typedef struct VNode{   //一个顶点
    VertexType data;
    ArcNode *firstarc;
}VNode,*AdjList;
typedef struct{
    AdjList vertices;	//顶点线性表
    int vexnum;			//顶点数
}ALGraph;
int Dijkstra(int start,int des,ALGraph G,int **path,double *cost);
void InitMap(ALGraph *G,char* filename);
double Weight(ALGraph G,int i,int j);
void PrintPath(ALGraph G,int *path,int n,double cost);
void PrintMap(ALGraph G);
int main(){
    int start,des,n,*path;
    double cost=0;
    char *filename="graph.txt";
    ALGraph map;
    system("cls");
    printf("<路径规划>\n加载地图: %s\n",filename);
    InitMap(&map,filename);
    n=map.vexnum;
    PrintMap(map);
    printf("请输入起点与终点编号(从1开始):");
    scanf("%d%d",&start,&des);
    if(start==des||start>n||start<=0||des>n||des<=0){
        printf("路径不可用!\n");
        exit(ERROR);
    }
    n=Dijkstra(start-1,des-1,map,&path,&cost);
    PrintPath(map,path,n,cost);
    system("pause");
}
void InitMap(ALGraph *G,char* filename){    //读取地图信息
//#格式:编号 城市名 相连城市编号1 相连城市1距离 ... 【换行符】
//编号从1开始,每一行以-1结尾
    FILE *fp=NULL;
    int i,n;
    ArcNode *p;
    if(!(fp=fopen(filename,"r"))) exit(ERROR);
    fscanf(fp,"%d",&G->vexnum);      //第一个数据为总顶点数量
    if(G->vexnum<=0) exit(ERROR);    //数据个数有误
    if(!((G->vertices)=(AdjList)calloc(G->vexnum,sizeof(VNode)))) exit(OVERFLOW);//分配顶点线性表空间
    for(i=0;i<G->vexnum&&!feof(fp);i++){
        fscanf(fp,"%d",&n);
        if(!(G->vertices[i].data=(VertexType)calloc(LISTINITSIZE,sizeof(char)))) exit(OVERFLOW);
        G->vertices[i].firstarc=NULL;
        fscanf(fp,"%s %d",G->vertices[i].data,&n);
        while(n>0&&!feof(fp)){
            if(!(p=(ArcNode*)malloc(sizeof(ArcNode)))) exit(OVERFLOW);
            p->nextarc=G->vertices[i].firstarc;
            G->vertices[i].firstarc=p;  //头插法
            fscanf(fp,"%lf",&p->weight);
            p->adjvex=n-1;
            fscanf(fp,"%d",&n);
        }
    }
    if(i!=G->vexnum) exit(ERROR);//地图数据缺少
    fclose(fp);
}
int Dijkstra(int start,int des,ALGraph G,int **path,double *cost){//Dijkstra算法规划路径,最后输出一个以-1结尾的整形数组
    int final[G.vexnum];//是否到达过各点
    double D[G.vexnum];//到各点的最短距离
    int Pre[G.vexnum];
    //记录从start到i顶点的路径中,i顶点的前一个顶点的下标
    int i,j,v;
    double min,a;
    ArcNode *p;
    for(i=0;i<G.vexnum;i++){
        final[i]=FALSE;
        D[i]=INF;
        Pre[i]=start;
    }
    for(p=G.vertices[start].firstarc;p;p=p->nextarc) D[p->adjvex]=Weight(G,start,p->adjvex);
    final[start]=TRUE;
    for(i=1;i<G.vexnum;i++){//i是计数器
        min=INF;
        for(j=0;j<G.vexnum;j++){//选出距离最小的j
            if(final[j]==FALSE&&D[j]<min){//若未访问过且有弧相连
                v=j;
                min=D[j];
            }
        }//for
        final[v]=TRUE;
        if(v==des) break;   //已经找到路径
        for(j=0;j<G.vexnum;j++){
            if(final[j]==FALSE&&((a=Weight(G,v,j))<D[j]-min)){
                D[j]=a+min;
                Pre[j]=v;
            }
        }
    }
    *cost=D[des];
    int inversepath[G.vexnum]; //终点到起点的路径,线性栈(由于Pre数组是倒序查找的)
    inversepath[0]=des;
    for(i=1,j=Pre[des];i<G.vexnum&&j!=start;i++,j=Pre[j]) inversepath[i]=j;
    inversepath[i]=start;
    if(!(*path=(int *)calloc(i+1,sizeof(int)))) exit(OVERFLOW);
    for(j=0;i>=0;j++,i--) (*path)[j]=inversepath[i];
    return j;
}
double Weight(ALGraph G,int i,int j)
{
    ArcNode *p;
    if(i==j) return 0.0;
    for(p=G.vertices[i].firstarc;p;p=p->nextarc) if(p->adjvex==j) break;
    if(!p) return INF;
    return p->weight;
}
void PrintPath(ALGraph G,int *path,int n,double cost)//输出路径
{
    int i;
    printf("从 %s 到 %s 的最短路径为: %s",G.vertices[path[0]].data,G.vertices[path[n-1]].data,G.vertices[path[0]].data);
    for(i=1;i<n;i++) printf("->%s",G.vertices[path[i]].data);
    putchar('\n');
    printf("总距离: %g km\n",cost);
}
void PrintMap(ALGraph G){    //打印地图数据
    int i;
    ArcNode *p;
    printf("地图加载完成:\n");
    for(i=0;i<G.vexnum;i++){
        printf("顶点%d: %s; 相连:",i+1,G.vertices[i].data);
        if(!(p=G.vertices[i].firstarc)) printf(" 不存在");
        while(p){
            printf(" 顶点%d,距离%g;",p->adjvex+1,p->weight);
            p=p->nextarc;
        }
        putchar('\n');
    }
}
  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值