目录

问题:

代码1(这是题目给的代码)

解析:

功能1:

功能2:

代码

代码2(自己写的)

前言

整体思路及运行情况

代码


问题:

背景知识:图的存储、遍历及其应用,图的最短路径等。

目的要求:

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

实验内容:

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

2.内容:

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

实验说明:

    1.输入和输出:

(1)输入形式:

  1. 构建图时,输入顶点、弧涉及的信息,包括:起始地、目的地、长度、该弧此时间段的平均速度等信息;
  2. 用户或者客户要输入出发地和目的地,并选择何种最优决策的路线规划。

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

  1. 输出最短路程所需要的路线信息和最短路程;
  2. 输出最短时间所需要的路线信息和最短时间。

2.实验要求:

    1. 实现一个简单的交互式界面,包括系统菜单、清晰的输入提示等。
    2. 根据输入的交通图数据,以图形化形式把交通图显示在屏幕上。
    3. 以图形化形式把最优路线显示在屏幕上。
代码1(这是题目给的代码)

解析:

这个是实验指导书上的源码,挺好用

功能1:

首先建立三个文本文件

数据结构:图及其应用_算法

count文件里面存的地方的个数,map文件里面存的是一个点到另一个点的距离,map_speed文件里面存的是 一个点到另一个点的时间

数据结构:图及其应用_算法_02数据结构:图及其应用_算法_03数据结构:图及其应用_算法_04

看map里面的1,处于第1行第2列,就是第一个点到第二个点的距离是1,

map_speed的1.1就是第1个点到第2个点的花费的时间是1.1

这是我用的测试点

 数据结构:图及其应用_算法_05

下面正式开始测试,首先你要改一下代码中的文件的路径,

数据结构:图及其应用_算法_06 数据结构:图及其应用_算法_07

 数据结构:图及其应用_算法_08

运行结果图

数据结构:图及其应用_算法_09

我们可以根据之前的测试图,可以看到它的路线

功能2:

录入路线

把代码中的写入的路径更改一下

数据结构:图及其应用_算法_10

数据结构:图及其应用_算法_11

这个输入的是两个点是双向都可以通的,点1到点2 的距离是1速度是1,

数据结构:图及其应用_算法_12

思路:很简单,就是用弗罗伊德算法,计算出权值最小的路径,顺便用记录中间的一些中转点,在最后的输出路径中输出出来。

弗罗里达算法思想,想具体知道弗罗里达算法算法自己在网上搜一下吧看吧。


代码

稍微加了一些注释,这个给的代码很简单,应该不用多说吧,不会真的有人看不懂吧

#include <stdio.h>
#include <stdlib.h>
#define inf 99999999
#define max_element 50
int e[max_element][max_element];  //保存地图的数组
int path_e[max_element][max_element], path_t[max_element][max_element];//转折点的路径
double t[max_element][max_element];  //保存地图的速度

void Menu();
void Old_Map();
void New_Map();
void Floyd(int (*e)[max_element],double (*t)[max_element], int n);       //计算最短路径
void Floyd_dist(int (*e)[max_element], int n, int start, int end);
void Floyd_time(double (*e)[max_element], int n, int start, int end);
int main()
{
    int Mu=5;
    Menu();
    while(scanf("%d", &Mu), Mu!=0)
    {
        switch(Mu)//菜单选项
        {
            case 1: Old_Map();break;
            case 2: New_Map();break;
            case 3: system("cls");break;
            default:printf("\n请输入正确指令!!!");break;
        }

        Menu();
    }
    printf("\n成功退出!");
    return 0;
}

void Menu()
{
    printf("\n    ---选择使用已保存的地图:1---");
    printf("\n\n    ---选择重新录入地图信息:2---\n");
    printf("\n    -----------清屏:3-----------\n");
    printf("\n  -------------退出:0-------------\n");
}
//使用原有地图
void Old_Map()
{
    int i, j;
    FILE *fp;
    int count = 0;
    //读入文档count.txt
    if((fp=fopen("C:\\Users\\jin\\Desktop\\count.txt","r")) == NULL)
    {
        printf("File open failed!\n");
        exit(0);
    }
    fscanf(fp,"%d", &count);//读入点数
    fclose(fp);
    printf("顶点个数 == %d\n", count);
    if(count == 0 )
    {
        printf("\n信息读入错误!!\n错误原因:没有已保存的地图,请选择重新输入地图信息!!\n");
        return ;
    }

    ///读入文档map.txt
    if((fp=fopen("C:\\Users\\jin\\Desktop\\map.txt","r")) == NULL)
    {
        printf("File open failed!\n");
        exit(0);
    }
    for(i = 1; i <= count; i++)
        for(j = 1; j <= count; j++)
        {
            fscanf(fp,"%d", &e[i][j]);
        }//读入距离地图,是一个矩阵
    fclose(fp);
    ///读入文档map_speed.txt
    if((fp=fopen("C:\\Users\\jin\\Desktop\\map_speed.txt","r")) == NULL)
    {
        printf("File open failed!\n");
        exit(0);
    }
    for(i = 1; i <= count; i++)
        for(j = 1; j <= count; j++)
        {
            fscanf(fp,"%lf", &t[i][j]);
        }//读入时间地图,矩阵
    fclose(fp);
    ///将地图信息打印*************能否采用图形界面将位置信息打印?

    Floyd(e,t, count);
}
//新录入地图
void New_Map()
{
    //map数组初始化
    int i, j;
    for(i = 0; i < max_element; i++ )
        for(j = 0; j < max_element; j++)
            if(i == j)
            {
                e[i][j] = 0;
                t[i][j] = 0;
            }

            else {
                    e[i][j] = inf;
                    t[i][j] = inf;
            }

    printf("\n请输入每条路的起点、终点、路的长度、速度\n(中间以空格隔开,按下Ctrl+Z结束输入):\n");
    int s, ee, l, speed;
    int count = 0;
    //地图写入
    while(scanf("%d %d %d %d", &s, &ee, &l,&speed) != EOF)
    {//开始地,目标地,距离,速度
        e[s][ee] = l;
        e[ee][s] = l;
        t[s][ee] = (l*1.0)/speed;
        t[ee][s] = (l*1.0)/speed;
        printf("%.2f ", t[s][ee]);
        count++;
    }
    ///将地图存入文件map.txt
    FILE *fp;
    if((fp=fopen("C:\\Users\\jin\\Desktop\\map1.txt","w")) == NULL)
    {
        printf("the file can not open...");
        exit(0);
    }
    for(i = 1; i <= count; i++)
        for(j = 1; j <= count; j++)
        {
            fprintf(fp,"%d", e[i][j]);
            fprintf(fp,"\n");
        }
    fclose(fp);

    ///将速度-时间存入文件中"map_speed.txt
    if((fp=fopen("C:\\Users\\jin\\Desktop\\map_speed1.txt","w")) == NULL)
    {
        printf("the file can not open...");
        exit(0);
    }
    for(i = 1; i <= count; i++)
        for(j = 1; j <= count; j++)
        {
            fprintf(fp,"%lf", t[i][j]);
            fprintf(fp,"\n");
        }//像文件里面写入速度(浮点数)
    fclose(fp);
    ///将顶点的个数存入文件
    if((fp=fopen("C:\\Users\\jin\\Desktop\\count1.txt","w")) == NULL)
    {
        printf("the file can not open...");
        exit(0);
    }
    fprintf(fp,"%d", count);
    fclose(fp);
    Floyd(e,t, count);
}
//佛洛依德算法
void Floyd(int (*e)[max_element],double (*t)[max_element],int n)
{
    int start, end; //起始位置,终点
    //初始化记录路径详细信息数组path
    int i, j;
   //初始化终点***
    for( i = 0; i <= n; i++)
        for(j = 0; j <= n; j++)
        {
            path_e[i][j] = j;
            path_t[i][j] = j;
        }

    while(1)
    {
        printf("\n请输入要查询路径起点、终点位置:");
        scanf("%d %d", &start, &end);
        if(start > n || end > n)
        {
            printf("\n出现错误!!!\n错误原因:输入了不存在的顶点!!\n请重新输入!!\n");
            printf("\n顶点个数为:%d", n);
            continue;
        }
        int Floyd_xuanze = 0;
        printf("\n请输入查询方式:\n");
        printf("1---最短路径\n");
        printf("2---最短时间\n");
        scanf("%d", &Floyd_xuanze);

        /**
         *异常处理
         */

        switch(Floyd_xuanze)
        {
            case 1: Floyd_dist(e, n, start, end);break;
            case 2: Floyd_time(t,n, start, end);break;
            default : printf("请输入正确指令!!!\n");break;
        }
        int temp = 0;
        printf("是否继续查询:yes:1 / no:0\n");
        scanf("%d", &temp);
        if(!temp)
            break;
    }

}
void Floyd_dist(int (*e)[max_element], int n, int start, int end)
{
    int k, i, j;
     ///佛洛依德算法---距离
    for(k = 1; k<=n; k++)//中转点
        for(i = 1; i <= n; i++)
            for(j = 1; j <= n; j++)
                if(e[i][j]>e[i][k]+e[k][j])
                {
                    e[i][j]=e[i][k]+e[k][j];
                    path_e[i][j] = path_e[i][k];//记录中转点
                }

    ///打印出最短路径及相应路径信息--距离
    printf("\n查询成功!!信息如下:\n\n");
    printf("%d=>%d, length:%d, ",start, end, e[start][end]);
    int v = path_e[start][end];//最开始的中转点
    printf("path:%d", start);
    while(v!=end)
    {
        printf("->%d",v);
        v = path_e[v][end];
    }
    printf("->%d", end);
    printf("\n___________________________________________\n");
}
void Floyd_time(double (*t)[max_element], int n, int start, int end)
{
    int k, i, j;

    ///佛洛依德算法---时间
    for(k = 1; k<=n; k++)
        for(i = 1; i <= n; i++)
            for(j = 1; j <= n; j++)
                if(t[i][j]>t[i][k]+t[k][j])
                {
                    t[i][j]=t[i][k]+t[k][j];
                    path_t[i][j] = path_t[i][k];
                }
    ///打印出最短路径及相应路径信息--距离
    printf("\n查询成功!!信息如下:\n\n");
    printf("%d=>%d, time:%.2fh, ",start, end, t[start][end]);
    int v = path_t[start][end];
    printf("path:%d", start);
    while(v!=end)
    {
        printf("->%d",v);
        v = path_t[v][end];
    }
    printf("->%d", end);
    printf("\n___________________________________________\n");
}
代码2(自己写的)

前言

如果你这个看的不是很懂,建议看第一个,

其实也没啥,就是实现一个中文的地点,用map容器进行映射。

其中的难点就是搞了我好久的一个小东西,读取文件,一个词,一个词的读取,搞得我很头疼,不过最后巧妙的解决啦

这个东西如果只用getline(ifs, read, ' '),读取文件的时候,当读取到第一行最后一个词的时候,会和第二行第一个词一起读,于是乎,可能应该搞了有点长时间把,想了一个巧妙的办法给解决啦,唉这就是生活啊,兵来将挡,水来土掩。

数据结构:图及其应用_算法_13

整体思路及运行情况

思路:读取文件里面给的路线图,把这些点用弗罗伊德算法,算出最优解,根据所求,输出所要。

主要的亮点就是中文的地点,用了map容器进行一些替换

运行情况:

首先把你的文件调整成ANSI编码,

数据结构:图及其应用_算法_14

在文件的输入格式是,开始地名,目的地名,距离(浮点型),速度(浮点型)

 

数据结构:图及其应用_算法_15

这是我的地图,画了一下

数据结构:图及其应用_算法_16

开始运行,首先你要知道你的文件的路径

 

数据结构:图及其应用_算法_17

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
map<string,int> pp;
map<int,string> qq;
#define inf 99999999
double dist[50][50],timee[50][50];
int locations = 0;
void Floyd(double mn[50][50],int choose);
void Choose();
void Floyd(double mn[50][50],int choose)
{
    int path_min[50][50];//记录中间转折点
    for(int i=1; i<=locations; i++)
        for(int j=1; j<=locations; j++)
            if(i!=j&&mn[i][j]==0)
            {
                mn[i][j] = inf;//初始化地图
                //cout<<dist[i][j]<<endl;
            }

    for(int i=1; i<=locations; i++)
        for(int j=1; j<=locations; j++)
        {
            path_min[i][j] = j;//初始化转折点
        }
    //弗罗里达算法
    for(int k = 1; k<=locations; k++)
        for(int i=1; i<=locations; i++)
            for(int j=1; j<=locations; j++)
            {
                if(mn[i][j]>mn[i][k]+mn[k][j])
                {
                    mn[i][j] = mn[i][k]+mn[k][j];
                    path_min[i][j] = path_min[i][k];
                }
            }
    while(1)
    {
        printf("请输入出发地名和目的地名\n");
        printf("出发地名:");
        string ss;
        cin>>ss;
        int st = pp[ss];

        printf("目的地名:");
        string sss;
        cin>>sss;
        int ed = pp[sss];
        cout<<"++++++++++++++++++++++++"<<endl;
        cout<<(choose == 1 ? "您所需的最短路程为:":"最短时间为:");
        cout<<mn[st][ed];
        cout<<(choose == 1 ? "公里" : "小时")<<endl;
        cout<<"++++++++++++++++++++++++"<<endl;
        cout<<"您的路线为:"<<endl;
        cout<<"------------------------"<<endl;
        cout<<ss<<"->";
        int v = path_min[st][ed];
        while(v!=ed)
        {
            cout<<qq[v]<<"->";
            v = path_min[v][ed];
        }
        cout<<sss<<endl;
        cout<<"------------------------"<<endl;
        cout<<"请问是选择再次询问,还是退出,还是返回上一级"<<endl;
        cout<<"\t1再次询问\n"<<"\t2.返回上一级\n"<<"\t3.退出\n"<<endl;
        int c;
        cin>>c;
        if(c==1) {}
        else if(c==2)
            Choose();
        else if(c==3)
            return;
    }
}
void Choose()
{
    printf("请选择查询方式\n");
    printf("1.最短路径\t");
    printf("2.最短时间\t\n");
    int choose;
    cin>>choose;
    if(choose==1)
    {
        Floyd(dist,choose);//最短路程
    }
    else if(choose==2)
    {
        Floyd(timee,choose);//最少时间
    }
    else
    {
        cout<<"您输入的指令有误,请重新输入"<<endl;
        Choose();
    }
}
int main()
{
    int id=1;
    cout<<"请输入您地图的位置"<<endl;
    string Path;
    cin>>Path;//输入位置
    char path[100];
    for(int i=0; i<Path.length(); i++)
        path[i] = Path[i];
    ifstream ifs(path);
    if(ifs!=NULL) cout<<"您的地图已被打开已经被打开"<<endl;
    string read;
    int ans = 0;
    string start,end;//出发地,目标地
    double dis,sp;//距离,速度
    while(getline(ifs, read, ' '))
    {
        if(ans%4==0)//读取的第一个词
        {
            start = read;
            //cout<<"开始地"<<read<<endl;
        }

        if(ans%4==1)//读取的第二个词
        {
            end = read;
            //cout<<"目标地"<<read<<endl;
        }

        if(ans%4==2)//读取的第三个词和第四个词
        {
            char s1[10];
            memset(s1,0,sizeof(s1));
            for(int i=0; i<read.length(); i++)
                s1[i] = read[i];
            dis = atof(s1);
            //cout<<dis<<"距离"<<read<<endl;
            getline(ifs, read, '\n');
            char s2[10];
            for(int i=0; i<read.length(); i++)
                s2[i] = read[i];
            sp = atof(s2);
            // cout<<"速度"<<read<<endl;
            ans++;
        }

        //cin>>start>>end>>dis>>sp;
        if(ans%4==3)//四个读取完开始储存
        {
            if(pp[start]==0)//如果这个地点没有被储存,便开始储存
            {
                pp[start] = id;//地点对应的序号
                qq[id] = start;
                id++;
            }
            if(pp[end]==0)
            {
                pp[end] = id;
                qq[id] = end;
                id++;
            }
            dist[pp[start]][pp[end]] = dis;//这段路的而距离
            timee[pp[start]][pp[end]] =dis/sp;//这段路的时间
            //cout<<dist[pp[start]][pp[end]]<<"--"<<timee[pp[start]][pp[end]]<<endl;
        }
        ans++;
    }

    map<string,int>::iterator it;
    for(it = pp.begin(); it!=pp.end(); it++)
    {
        locations++;//统计共有几个地点
        //cout<<it->first<<"--"<<it->second<<endl;
    }
    /*for(int i=1; i<=5; i++)
    {
        cout<<qq[i]<<endl;
    }*/
    //cout<<locations<<endl;
    Choose();
    return 0;
}