(Dijkstra算法)设计实现一个全国大城市间的交通咨询程序,为旅客提供三种最优决策方案:(1)飞行时间最短(2)费用最小(3)中转次数最少。

设计实现一个全国大城市间的交通咨询程序,为旅客提供三种最优决策方案:

1)飞行时间最短

(2)费用最小

(3)中转次数最少

数据如下:

机  号                     

出 发 地

到 达 地

出发时间

到达时间

费  用 

6320

北京

上海

上海

北京

16:20

18:00  

17:25

19:05

680元

2104

北京

乌鲁木齐

乌鲁木齐

  北京

8:00

10:45

9:55

11:40

1150元

201

  北京

  西安

  西安

  北京

15:25

12:35

17:00

14:15

930元

2323

  西安

广州

  广州

  西安

7:15

10:15

9:35

11:35

1320元

173

  拉萨

  昆明

  昆明

拉萨

10:20

12:35

11:45

14:00

830元

3304

  拉萨

  武汉

  武汉

拉萨

14:15

16:25

15:45

17:55

890元

82

  乌鲁木齐

    昆明

  昆明

乌鲁木齐 

9:30

13:05

12:15

15:50

1480元

4723

  武汉

广州

 广州

 武汉

7:05

11:25

8:45

13 :05

810元

这是一道数据结构的题目,知识点为数据结构中的图,利用迪杰斯特拉(Dijkstra)算法求解单源路径最短问题。

关于Dijkstra算法的思路:

1.将图上的初始点看作一个集合S,其它点看作另一个集合

2.根据初始点,求出其它点到初始点的距离d[i] (若相邻,则d[i]为边权值;若不相邻,则d[i]为无限大)

3.选取最小的d[i](记为d[x]),并将此d[i]边对应的点(记为x)加入集合S

(实际上,加入集合的这个点的d[x]值就是它到初始点的最短距离)

4.再根据x,更新跟 x 相邻点 y 的d[y]值:d[y] = min{ d[y], d[x] + 边权值w[x][y] },因为可能把距离调小,所以这个更新操作叫做松弛操作。

( 因为第三步只更新并确定了x点到初始点的最短距离,集合内其它点是之前加入的,也经历过第 4 步,所以与 x 没有相邻的点的 d 值是已经更新过的了,不会受到影响)

5.重复3,4两步,直到目标点也加入了集合,此时目标点所对应的d[i]即为最短路径长度。

具体操作可以看这个例子,动图很快,最好自己动手一步一步地操作一遍就大概懂了

Dijkstra算法示例

声明:这里的Dijkstra算法讲解参考了另一位博主的文章,链接如下https://blog.csdn.net/Kprogram/article/details/81225176

下面开始编程思路分析:

        查询8个城市中任意城市到其他城市的最低价,最短时间和最短路径信息,也就是对8个不同数据元进行三种不同的操作。而这三个操作又有共同特点,查询最短距离,最低价格,最短时间,都是求图中一个顶点到其他所有顶点的最短距离,只是权值不一样,核心都是单源路径最短问题,用的算法都是Dijkstra算法。所以可以单独写一个迪杰斯特拉算法,根据三种不同需求,传入边权值,返回对应的最短路径。这样避免了代码的重复。

代码演示:

头文件MGraph.h

#include <stdio.h>
#define maxVertices 30   //图中顶点数目的最大值
#define maxEdges 900     //最大边数
#define maxWeight 32767
#define impossibleVablue '#'
#define impossibleWeight -1
typedef int Type;		//顶点数据的数据类型
typedef int Weight;		//边上权值的数据类型
typedef struct{
    int numVertices,numEdges;					//图中实际顶点个数和边的条数
    Type VerticesList[maxVertices];				//顶点表
    Weight Edge[maxVertices][maxVertices]; 		//邻接矩阵
}MGraph;


int getVertexPos(MGraph& G,Type x)		//从顶点的数据值找出该顶点的顶点号,如果查找失败,返回-1
{
    for(int i=0;i<G.numVertices;i++)
    {
        if(G.VerticesList[i]==x)
            return i;
    }
    return -1;
}


int numberOfVertices(MGraph& G)   //返回图中当前已有的顶点个数
{
    return G.numVertices;
}

void createMGraph(MGraph& G,Type v[],int n,Type ed[][2],Weight c[],int e)  //顶点数据存放在v[],边的顶点对分别存放于ed[e][0],ed[e][1],权值存放在c[e]
{
    G.numVertices=n;G.numEdges=e;
    int i,j,k;
    for(i=0;i<G.numVertices;i++)   //初始化
    {
        G.VerticesList[i]=v[i];
        for(j=0;j<G.numVertices;j++)
            G.Edge[i][j]=(i==j) ? 0:maxWeight;			//初始化邻接矩阵 
    }
    for(k=0;k<G.numEdges;k++)      //建立邻接矩阵
    {
        i=getVertexPos(G,ed[k][0]);  //使用ed[][]将顶点值转换为顶点号,建立图 
        j=getVertexPos(G,ed[k][1]);
        G.Edge[i][j]=c[k];         //边赋值
    }
}

void ShortestPath(MGraph& G,int v,Weight dist[],int path[])//dist[j]存放当前求到的从顶点v到顶点j的最短路径长度,path[j]存放求到的最短路径长度
{
    int n=numberOfVertices(G);
    int S[maxVertices];//最短路径顶点集
    int i,j,k;
    Weight w,min;
    for(i=0;i<n;i++)
    {
        dist[i]=G.Edge[v][i];
        S[i]=0;
        if(i!=v&&dist[i]<maxWeight)
            path[i]=v;
        else
            path[i]=-1;
    }
    S[v]=1;  dist[v]=0;  //顶点v加入S集合
    for(i=0;i<n-1;i++)
    {
        min=maxWeight;
        int u=v;
        for(j=0;j<n;j++)
            if(!S[j]&&dist[j]<min){
                u=j;
                min=dist[j];
            }
        S[u]=1;
        for(k=0;k<n;k++){
            w=G.Edge[u][k];
            if(!S[k]&&w < maxWeight && dist[u]+w < dist[k])
            {
                dist[k]=dist[u]+w;
                path[k]=u;//顶点k未加入S,且绕过u可以缩短路径
            }
        }

    }

}

void printShortestPath_price(MGraph& G,int v,Weight dist[],int path[])
{
    printf("从城市[%d]到其他城市的费用为:\n",G.VerticesList[v]);
    int i,j,k,n=numberOfVertices(G);
    int d[maxVertices];
    for(i=0;i<n;i++)  //逐个顶点输出v0-vi最短路径
        if(i!=v){
            j=i;k=0;
            while(j!=v){
                d[k++]=j;
                j=path[j];
            }
            d[k++]=v;
            printf("到城市[%d]的最短路径长度为:",G.VerticesList[i]);
            while(k>0)
                printf("%d",G.VerticesList[d[--k]]);
        printf("\n费用为:%d元\n",dist[i]);
    }
}


void printShortestPath_time(MGraph& G,int v,Weight dist[],int path[])
{
    printf("从城市[%d]到其他城市的飞行时间为:\n",G.VerticesList[v]);
    int i,j,k,n=numberOfVertices(G);
    int d[maxVertices];
    for(i=0;i<n;i++)
    if(i!=v){
        j=i;k=0;
        while(j!=v){
            d[k++]=j;
            j=path[j];
        }
        d[k++]=v;
        printf("到城市[%d]的最短路径长度为:",G.VerticesList[i]);
        while(k>0)
            printf("%d",G.VerticesList[d[--k]]);
        printf("\n飞行时间为:%d\n",dist[i]);
    }
}

void printShortestPath_num(MGraph& G,int v,Weight dist[],int path[])
{
    printf("从城市[%d]到其他城市的中转次数为:\n",G.VerticesList[v]);
    int i,j,k,n=numberOfVertices(G);
    int d[maxVertices];
    for(i=0;i<n;i++)
    if(i!=v){
        j=i;k=0;
        while(j!=v){
            d[k++]=j;
            j=path[j];
        }
        d[k++]=v;
        printf("到城市[%d]的最短路径长度为:",G.VerticesList[i]);
        while(k>0)
            printf("%d",G.VerticesList[d[--k]]);
        printf("\n中转次数为:%d\n",dist[i]-1);
    }
}

主函数main.cpp

#include "MGraph.h"
#include <iostream>
using namespace std;
int main()
{
    MGraph G;

    int location,operation;
    int n=8,e=16;
    int path[20];


    Type v[8]={0,1,2,3,4,5,6,7};
    Type ed[16][2]={0,1,1,0,0,2,2,0,0,3,3,0,3,4,4,3,5,6,6,5,5,7,7,5,2,6,6,2,7,4,4,7};		//存储图中的链接情况,数值为各个地点的编号,16组是因为8对顶点,相互有16个关系。 
    Weight a[16]={680,680,1150,1150,930,930,1320,1320,830,830,890,890,1480,1480,810,810}; //价格权值 
    Weight b[16]={65,65,115,115,95,95,140,140,85,85,90,90,165,165,100,100}; 	//时间权值 
    Weight c[16]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};			//中转次数权值 
    Weight dist[100];

    cout <<"请输入开始的城市(0:北京,1:上海:2:乌鲁木齐,3:西安,4:广州,5:拉萨,6:昆明,7:武汉):"<<endl;
    cin >> location;
    cout << "请输入选择的操作(1:查询最低价格,2:查询最短飞行时间,3:中转次数最少):" << endl;
    cin >> operation;

    switch(operation){
    case 1:{
        createMGraph(G,v,n,ed,a,e);
        ShortestPath(G,location,dist,path);
        printShortestPath_price(G,location,dist,path);
        break;}
    case 2:{
        createMGraph(G,v,n,ed,b,e);
        ShortestPath(G,location,dist,path);
        printShortestPath_time(G,location,dist,path);
        break;}
    case 3:{
        createMGraph(G,v,n,ed,c,e);
        ShortestPath(G,location,dist,path);
        printShortestPath_num(G,location,dist,path);
        break;}
    default:
        break;
    }

    return 0;



}

在同一个文件夹下运行,得到结果为:

路径数字为城市代码的顺序

OVER

发布了27 篇原创文章 · 获赞 19 · 访问量 4549

猜你喜欢

转载自blog.csdn.net/qq_43617268/article/details/103449525