运用Dijkstra方法求最短路径

数据结构之图及其应用

一,目的

  • 掌握图的存储、构建、搜索等操作和应用,能用最短路径及其搜索等算法编制较综合性的程序,求解最优路线问题,进行程序设计、数据结构和算法设计等方面的综合训练。

  • 设计一个城市交通咨询模拟系统,利用该系统实现至少两种最优决策:最短路程到达、最省时到达等线路规划。

二,描述

用户驾车出行由于出行目的的不同对道路路线选择的要求也有不同。例如,有的希望在途中的路程尽可能短,有的则可能希望路程中时间最短。为了能满足广大旅客的需求,编制一个城市交通咨询模拟系统,选取城市部分位置、道路抽象为程序所需要图的顶点和边,并以城市道路长度(路程),道路的某时段的速度等信息作为图结点中的弧信息,为旅客提供这两种最优决策的交通咨询。

输入和输出:

(1)输入形式:

​ 构建图时,输入顶点、弧涉及的信息,包括:起始地、目的地、长度、该弧此时间段的平均速度等信息;

​ 用户或者客户要输入出发地和目的地,并选择何种最优决策的路线规划。

(2)输出形式:根据用户需求输出对应信息

​ 输出最短路程所需要的路线信息和最短路程;

​ 输出最短时间所需要的路线信息和最短时间。

三,代码测试

在这里插入图片描述

四,部分源码

  1. 主要数据类型与变量

    typedef struct{
        bool visit = false;
        double value = 0;
        double time = 0;
        string path = "";
    }Dis;
    
    typedef struct{
    	int vexnum;   //图的顶点个数
        int edge;     //图的边数
        double **arc;   //路程邻接矩阵
        double **arc1;  //时间邻接矩阵 
        Dis * dis;   //记录各个顶点最短路径的信息
        Dis * dis1;   //记录各个顶点最短时间的信息
    }Graph;
    
  2. 部分函数模块

    //检验输入边数和顶点数的值是否有效
    bool check(int Vexnum, int edge);
    //构造函数
    void Graph_DG(int vexnum, int edge, Graph &H) {
        //为邻接矩阵开辟空间和赋初值
        H.edge = edge;
        H.vexnum = vexnum;
        H.arc = new double*[vexnum];
        H.arc1 = new double*[vexnum];
        H.dis = new Dis[vexnum];
        H.dis1 = new Dis[vexnum];
        for (int i = 0; i < vexnum; i++) {
            H.arc[i] = new double[vexnum];
            for (int k = 0; k < vexnum; k++) {
                //邻接矩阵初始化为无穷大
                    H.arc[i][k] = INT_MAX;
            }
        }
        for (int i = 0; i < vexnum; i++) {
            H.arc1[i] = new double[vexnum];
            for (int k = 0; k < vexnum; k++) {
                //邻接矩阵初始化为无穷大
                    H.arc1[i][k] = INT_MAX;
            }
        }
    }
    // 判断我们每次输入的的边的信息是否合法,顶点从1开始编号
    bool check_edge_value(int start, int end, int weight, Graph H);
        
    //创建图
    void createGraph(Graph &H) {
        cout << "请输入每条边的起点和终点(顶点编号从1开始)以及其长度和平均速度" << endl;
        int start;
        int end;
        double weight;
        double speed;  
        int count = 0;
        while (count != H.edge) {
            cin >> start >> end >> weight >> speed;
            //首先判断边的信息是否合法
            while (!check_edge_value(start, end, weight, speed, H)) {
                cout << "输入的边的信息不合法,请重新输入" << endl;
                cin >> start >> end >> weight >>speed;
            }
            //对邻接矩阵对应上的点赋值
            H.arc[start - 1][end - 1] = weight;
            H.arc1[start - 1][end - 1] = weight/speed;
            ++count;
        }
    }
    
    //打印邻接矩阵
    void print(Graph H);
    //求最短路径
    void Dijkstra1(Graph H, int begin){
        //首先初始化我们的dis数组
        int i;
        for (i = 0; i < H.vexnum; i++) {
            //设置当前的路径
            H.dis1[i].path = "v" + to_string(begin) + "-->v" + to_string(i + 1);
            H.dis1[i].value = H.arc1[begin - 1][i];
        }
        //设置起点的到起点的路径为0
        H.dis1[begin - 1].value = 0;
        H.dis1[begin - 1].visit = true;
    
        int count = 1;
        //计算剩余的顶点的最短路径(剩余this->vexnum-1个顶点)
        while (count != H.vexnum) {
            //temp用于保存当前dis数组中最小的那个下标
            //min记录的当前的最小值
            int temp=0;
            int min = INT_MAX;
            for (i = 0; i < H.vexnum; i++) {
                if (!H.dis1[i].visit && H.dis1[i].value<min) {
                    min = H.dis1[i].value;
                    temp = i;
                }
            }
            //cout << temp + 1 << "  "<<min << endl;
            //把temp对应的顶点加入到已经找到的最短路径的集合中
            H.dis1[temp].visit = true;
            ++count;
            for (i = 0; i < H.vexnum; i++) {
                //注意这里的条件H.arc[temp][i]!=INT_MAX必须加,不然会出现溢出,从而造成程序异常
                if (!H.dis1[i].visit && H.arc1[temp][i]!=INT_MAX && (H.dis1[temp].value + H.arc1[temp][i]) < H.dis1[i].value) {
                    //如果新得到的边可以影响其他为访问的顶点,那就就更新它的最短路径和长度
                    H.dis1[i].value = H.dis1[temp].value + H.arc1[temp][i];
                    H.dis1[i].path = H.dis1[temp].path + "-->v" + to_string(i + 1);
                }
            }
        }
    
    }
    void print_path(Graph H, int begin);//打印最短路径
    void Dijkstra1(Graph H, int begin);//初始化我们的dis数组
    void print_path1(Graph H, int begin); //打印最短时间
    

    主函数

    int main() {
        int vexnum; int edge;
    
        cout << "输入图的顶点个数和边的条数:" << endl;
        cin >> vexnum >> edge;
        
        while (!check(vexnum, edge)) {
            cout << "输入的数值不合法,请重新输入" << endl;
            cin >> vexnum >> edge;
        }
        Graph H;
        Graph_DG(vexnum, edge, H);
        
        createGraph(H);
    //	print(H);
    	Dijkstra(H, 1);
    	print_path(H, 1);
    	Dijkstra1(H, 1);
    	print_path1(H, 1);
        system("pause");
        return 0;
    }
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值