數據結構:圖及其應用

目錄

問題:

代碼1(這是題目給的代碼)

解析:

功能1:

功能2:

代碼

代碼2(自己寫的)

前言

整體思路及運行情況

代碼


問題:

背景知識圖的存儲、遍歷及其應用,圖的最短路徑等。

目的要求:

掌握圖的存儲、構建、搜索等操作和應用,能用最短路徑及其搜索等算法編制較綜合性的程序,求解最優路線問題,進行程序設計、數據結構和算法設計等方面的綜合訓練。

實驗內容:

1.任務:設計一個城市交通諮詢模擬系統,利用該系統實現至少兩種最優決策:最短路程到達、最省時到達等線路規劃。

2.內容:

用戶駕車出行由於出行目的的不同對道路路線選擇的要求也有不同。例如,有的希望在途中的路程儘可能短,有的則可能希望路程中時間最短。爲了能滿足廣大旅客的需求,編制一個城市交通諮詢模擬系統,選取城市部分位置、道路抽象爲程序所需要圖的頂點和邊,並以城市道路長度(路程),道路的某時段的速度等信息作爲圖結點中的弧信息,爲旅客提供這兩種最優決策的交通諮詢。

驗說明:

    1.輸入和輸出:

(1)輸入形式:

  1. 構建圖時,輸入頂點、弧涉及的信息,包括:起始地、目的地、長度、該弧此時間段的平均速度等信息;
  2. 用戶或者客戶要輸入出發地和目的地,並選擇何種最優決策的路線規劃。

(2)輸出形式:根據用戶需求輸出對應信息

  1. 輸出最短路程所需要的路線信息和最短路程;
  2. 輸出最短時間所需要的路線信息和最短時間。

2.實驗要求:

    1. 實現一個簡單的交互式界面,包括系統菜單、清晰的輸入提示等。
    2. 根據輸入的交通圖數據,以圖形化形式把交通圖顯示在屏幕上。
    3. 以圖形化形式把最優路線顯示在屏幕上。

代碼1(這是題目給的代碼)

解析:

這個是實驗指導書上的源碼,挺好用

功能1:

首先你需要改代碼的路徑,也就是你存放文件的位置、,一共有三個文件

count文件裏面存的地方的個數,map文件裏面存的是一個點到另一個點的距離,map_speed文件裏面存的是 一個點到另一個點的時間

看map裏面的1,處於第1行第2列,就是第一個點到第二個點的距離是1,

map_speed的1.1就是第1個點到第2個點的花費的時間是1.1

這是我用的測試點

 

下面正式開始測試,首先你要改一下代碼中的文件的路徑,

 

 

運行結果圖

我們可以根據之前的測試圖,可以看到它的路線

功能2:

錄入路線

把代碼中的寫入的路徑更改一下

這個輸入的是兩個點是雙向都可以通的,點1到點2 的距離是1速度是1,

思路:很簡單,就是用弗羅伊德算法,計算出權值最小的路徑,順便用記錄中間的一些中轉點,在最後的輸出路徑中輸出出來。

弗羅裏達算法思想,想具體知道弗羅裏達算法算法自己在網上搜一下吧看吧。


代碼

稍微加了一些註釋,這個給的代碼很簡單,應該不用多說吧,不會真的有人看不懂吧

#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, ' '),讀取文件的時候,當讀取到第一行最後一個詞的時候,會和第二行第一個詞一起讀,於是乎,可能應該搞了有點長時間把,想了一個巧妙的辦法給解決啦,唉這就是生活啊,兵來將擋,水來土掩。

整體思路及運行情況

思路:讀取文件裏面給的路線圖,把這些點用弗羅伊德算法,算出最優解,根據所求,輸出所要。

主要的亮點就是中文的地點,用了map容器進行一些替換

運行情況:

首先把你的文件調整成ANSI編碼,

在文件的輸入格式是,開始地名,目的地名,距離(浮點型),速度(浮點型)

 

這是我的地圖,畫了一下

開始運行,首先你要知道你的文件的路徑

 

代碼

#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];
            for(int i=0; i<read.length(); i++)
                s1[i] = read[i];
            dis = atof(s1);
            // cout<<"距離"<<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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章