1. 程式人生 > >數據結構實訓——校園導遊系統

數據結構實訓——校園導遊系統

鄰接矩陣 ros 比賽 遊覽 邊表 != arch 分享 png

1 課題描述

設計一個校園導遊程序,為來訪的客人提供各種信息查詢服務。查詢服務有:提供任意景點的信息,提供任意兩點之間的最短路徑,提供任意景點之間的所有路徑,提供多個景點之間的最佳訪問路徑。

2 問題分析和任務定義

任務要求:

1、 設計你的學校的校園平面圖,所含景點10-15個。以圖中頂點表示校園內各景點,存放景點名稱、代號、簡介等信息;以邊表示路徑,存放路徑長度等相關信息。

2、 為來訪客人提供圖中任意景點相關信息的查詢。

3、 為來訪客人提供圖中任意景點的問路查詢,即查詢任意兩個景點之間的一條最短的簡單路徑。

4、 提供圖中任意景點問路查詢,即求任意兩個景點之間的所有路徑。

5、 提供校園圖中多個景點的最佳訪問路線查詢,即求途經這多個景點的最佳路徑。

6、 區分汽車線路與步行線路。

7、 設計一實用的查詢界面和功能菜單。

3 邏輯設計

根據高德地圖獲得山東工商學院的平面圖,根據平面圖抽象出各個景點以及其大體距離和位置關系。

技術分享圖片

技術分享圖片

技術分享圖片

4 詳細設計

景點圖的結構體:

struct vertex///景點信息結構體

{

int num;///景點編號

char name[20];///景點名稱

char info[300];///景點介紹

};

struct maps

{

int n;///點數

int m;///邊數

vertex v[M];

int edgs[M][M];///鄰接矩陣

} ; ///景點圖的結構體

<1>獲得景點信息函數:void Creat_vertex()

將各個景點對應的信息存入景點信息結構體數組中。

<2>生成圖和鄰接矩陣函數: void Creat_maps()

將獲得的景點信息構成鄰接矩陣來存圖。

<3>查詢景點信息函數:void Search_info()

通過選擇菜單,查詢任意一個景點的信息。

<4>多源最短路弗洛伊德算法:void Floyd()

通過弗洛伊德算法實現任意一點到n-1點最短路的建立。

<5>打印最短路徑函數:void Floyd_print(int s, int e)

回溯弗洛伊德算法打印從s點到e點的最短路徑經過的點,並統計所走的總路程。

<6>打印兩點之間所有路徑函數:void Dfs_allpath(int s,int e)

通過DFS深度優先搜索打印從s點到e點的所有路徑。

<7>提供多景點之間最佳路徑函數:void Bestpath_Multispot()

打印多個景點之間的最短路徑,並統計所要走的總路程。

5 程序編碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#define INF 999999
#define M 20
int dist[M][M];///距離
int path[M][M];///路徑
int Stack[M];///路徑棧
int top;///棧頂
int counts;///記錄路徑數
int visited[M];///標記數組
using namespace std;
struct vertex///景點信息結構體
{
    int num;///景點編號
    char name[20];///景點名稱
    char info[300];///景點介紹
};
struct maps
{
    int n;///點數
    int m;///邊數
    vertex v[M];
    int edgs[M][M];///鄰接矩陣
} g; ///景點圖的結構體
void Creat_vertex()
{
    g.v[0].num=1;
    strcpy(g.v[0].name,"教職工家屬樓");
    strcpy(g.v[0].info,"這是學校老師職工的家屬樓");
    g.v[1].num=2;
    strcpy(g.v[1].name,"大學生活動中心");
    strcpy(g.v[1].info,"這是舉辦文藝活動的場所");
    g.v[2].num=3;
    strcpy(g.v[2].name,"餐飲區");
    strcpy(g.v[2].info,"這裏集中著學校的三大餐廳,物美價廉");
    g.v[3].num=4;
    strcpy(g.v[3].name,"辦公實驗樓");
    strcpy(g.v[3].info,"8樓一下是學生實驗區,以上是領導老師的辦公區域");
    g.v[4].num=5;
    strcpy(g.v[4].name,"四教");
    strcpy(g.v[4].info,"這是學校的第四座教學樓");
    g.v[5].num=6;
    strcpy(g.v[5].name,"五教");
    strcpy(g.v[5].info,"這是學校的第五座教學樓");
    g.v[6].num=7;
    strcpy(g.v[6].name,"二教");
    strcpy(g.v[6].info,"這是學校的第二座教學樓,也是計算機科學與技術學院的系樓");
    g.v[7].num=8;
    strcpy(g.v[7].name,"圖書館");
    strcpy(g.v[7].info,"這是學校的圖書館,藏書豐富,是同學們閱讀自習的好去處");
    g.v[8].num=9;
    strcpy(g.v[8].name,"三教");
    strcpy(g.v[8].info,"這是學校的第三座教學樓");
    g.v[9].num=10;
    strcpy(g.v[9].name,"體育館");
    strcpy(g.v[9].info,"這是學生進行室內比賽和體育活動的場所");
    g.v[10].num=11;
    strcpy(g.v[10].name,"男生宿舍");
    strcpy(g.v[10].info,"這是東校男生休息生活區域,有兩座巨大的樓");
    g.v[11].num=12;
    strcpy(g.v[11].name,"東操場");
    strcpy(g.v[11].info,"這是東校的田徑操場,同學們都在這裏鍛煉身體");
    g.v[12].num=13;
    strcpy(g.v[12].name,"落雪湖");
    strcpy(g.v[12].info,"這是學校的一座人工湖");
}
void Creat_maps()
{
    int i,j;
    g.n=13;///13個景點
    g.m=18;///18條雙向路徑
    for(i=0; i<g.n; i++) ///初始化鄰接矩陣
    {
        for(j=0; j<g.n; j++)
        {
            g.edgs[i][j]=INF;
        }
    }
    g.edgs[0][1]=g.edgs[1][0]=500;///寫入邊的信息
    g.edgs[0][2]=g.edgs[2][0]=1000;
    g.edgs[0][7]=g.edgs[7][0]=500;
    g.edgs[1][3]=g.edgs[3][1]=200;
    g.edgs[1][4]=g.edgs[4][1]=200;
    g.edgs[2][7]=g.edgs[7][2]=400;
    g.edgs[2][10]=g.edgs[10][2]=300;
    g.edgs[3][4]=g.edgs[4][3]=300;
    g.edgs[4][5]=g.edgs[5][4]=300;
    g.edgs[4][6]=g.edgs[6][4]=100;
    g.edgs[5][6]=g.edgs[6][5]=300;
    g.edgs[5][8]=g.edgs[8][5]=200;
    g.edgs[6][8]=g.edgs[8][6]=200;
    g.edgs[6][12]=g.edgs[12][6]=100;
    g.edgs[6][7]=g.edgs[7][6]=200;
    g.edgs[8][9]=g.edgs[9][8]=500;
    g.edgs[9][11]=g.edgs[11][9]=450;
    g.edgs[10][11]=g.edgs[11][10]=300;
}
void Search_info()
{
    int i,n;
    printf("山東工商學院東校區的景點有:\n");
    for(i=0; i<13; i++)
    {
        printf("%d:%s\n",g.v[i].num,g.v[i].name);
    }
    while(1)
    {
        printf("請輸入你想要查詢的景點編號:\n");
        printf("按0退出\n\n");
        scanf("%d",&n);
        getchar();
        if(n==0)
        {
            break;
        }
        else if(n<0||n>13)
        {
            printf("輸入有誤,請重新輸入!!!\n\n");
            continue;
        }
        else
        {
            printf("%d:%s\n",g.v[n-1].num,g.v[n-1].name);
            printf("%s\n\n",g.v[n-1].info);
        }
    }
    return ;
}
void Floyd() ///弗洛伊德
{
    int i,j,k;
    for(i=0; i<g.n; i++) ///初始化距離與路徑矩陣
    {
        for(j=0; j<g.n; j++)
        {
            dist[i][j]=g.edgs[i][j];
            if(i!=j&&dist[i][j]<INF)
            {
                path[i][j]=i;
            }
            else
            {
                path[i][j]=-1;///-1代表不可達
            }
        }
    }
    //printf("%d\n",g.n);
    for(k=0; k<g.n; k++)
    {
        for(i=0; i<g.n; i++)
        {
            for(j=0; j<g.n; j++)
            {
                if(dist[i][j]>(dist[i][k]+dist[k][j]))
                {
                    dist[i][j]=dist[i][k]+dist[k][j];///更新
                    path[i][j]=k;         ///path用於記錄最短路徑上的結點*/
                }
            }
        }
    }
    return ;
}
void Floyd_print(int s, int e)
{
    if(path[s][e]==-1||path[s][e]==e||path[s][e]==s)///遞歸終止條件
    {
        return;
    }
    else
    {
        Floyd_print(s,path[s][e]);///將中間點作為終點繼續打印路徑
        printf("%s->",g.v[path[s][e]].name);///打印中間景點名字
        Floyd_print(path[s][e],e);///將中間點作為起點繼續打印路徑
    }
}

void Dfs_allpath(int s,int e)
{
    int dis=0;
    int i,j;
    Stack[top]=s;
    top++;  ///起點入棧
    visited[s]=1;///標記入棧
    for(i=0; i<g.n; i++)
    {
        if(g.edgs[s][i]>0&&g.edgs[s][i]!=INF&&!visited[i])
        {
            ///表明兩點可達且未被訪問
            if(i==e)///DFS到了終點,打印路徑
            {
                printf("第%d條路:",counts++);
                for(j=0; j<top; j++)
                {
                    printf("%s->",g.v[Stack[j]].name);
                    if(j<top-1)///統計路徑長度
                    {
                        dis=dis+g.edgs[Stack[j]][Stack[j+1]];
                    }
                }
                dis=dis+g.edgs[Stack[top-1]][e];
                printf("%s\n",g.v[e].name);///打印終點
                printf("總長度是:%dm\n\n",dis);
            }
            else///不是終點接著DFS
            {
                Dfs_allpath(i,e);
                top--;///支路全被訪問一遍,頂點出棧
                visited[i]=0;///出棧點標記為已出棧,允許下次訪問
            }
        }
    }
}
void Bestpath_Multispot()
{
    int vNum[M]= {0};
    int i,j,dis;
    j=1;
    dis=0;///統計全程總長
    printf("請輸入你要遊覽的第%d個景點的編號(輸入-1結束輸入):",j);
    scanf("%d",&vNum[j-1]);
    while(vNum[j-1]!=-1&&j<13)
    {
        printf("請輸入你要遊覽的第%d個景點編號:",++j);
        scanf("%d", &vNum[j-1]);
        if(vNum[j-1]==-1)
        {
            break;
        }
    }
    printf("\n這是最佳訪問路徑:");
    for(i=0; vNum[i]>0&&vNum[i+1]>0; i++)
    {
        printf("%s->",g.v[vNum[i]-1].name);///輸出路徑上的起點
        Floyd_print(vNum[i]-1,vNum[i+1]-1);///利用佛洛依德算法
        dis+=dist[vNum[i]-1][vNum[i+1]-1];
    }
    printf("%s\n\n",g.v[vNum[j-2]-1].name);///*輸出路徑上的終點*/
    printf("全程總長為:%dm\n\n",dis);
}

void Dis_menu()
{
    printf("\n");
    printf("       ************歡迎使用山東工商學院導遊咨詢系統***********\n\n");
    printf("       *****   1.山商景點信息查詢           ******************\n");
    printf("       *****   2.兩景點之間最短路查詢       ******************\n");
    printf("       *****   3.兩景點間所有路徑查詢       ******************\n");
    printf("       *****   4.多景點間訪問路線查詢       ******************\n");
    printf("       *****   5.退出系統                   ******************\n");
    printf("       *******************************************************\n");
    return ;
}
void Dis_map()
{
    printf("\n                          *山商東校區校園景點地圖一覽*\n\n");
    printf("                                                               ⑽體育館       \n");
    printf("                                 ⑹五教      ⑼三教              ◎------|    \n");
    printf("                                    ◎          ◎---------------|       |    \n");
    printf("                                    |------------|               |       |    \n");
    printf("                                                 |               |------◎    \n");
    printf("                          ⑸四教          ⑺二教 |     (13)落雪湖|   ⑿東操場 \n");
    printf("                          ◎                    ◎      ◎       |       |    \n");
    printf("      ⑷辦公實驗樓◎-------|------------------—-|------|---------|       |    \n");
    printf("                |          |                    |               ◎-------|    \n");
    printf("                |          |                    |            ⑾ 男生宿舍     \n");
    printf("                |          |                    ◎               |            \n");
    printf("                ◎⑵大學生活動中心             ⑻圖書館          |            \n");
    printf("                |--------------------------------|               |            \n");
    printf("                |                                |---------------⑶餐廳        \n");
    printf("                |                                                            \n");
    printf("                ◎⑴ 職工家屬樓                                                \n\n");
}
int main()
{
    int i,n;
    int start,ends;
    Creat_vertex();
    Creat_maps();
    Dis_map();
    while(1)
    {
        Dis_menu();
        printf("請輸入需要操作的命令:\n");
        scanf("%d",&n);
        getchar();
        if(n<1||n>5)
        {
            printf("輸入有誤,請重新輸入!!!\n");
            continue;
        }
        else
        {
            if(n==1)
            {
                Search_info();
            }
            else if(n==2)
            {
                Dis_map();
                printf("請輸入起點的景點:\n");
                scanf("%d",&start);
                printf("請輸入終點的景點:\n");
                scanf("%d",&ends);
                Floyd();///弗洛伊德
                printf("從%s到%s最短距離是:%d\n",g.v[start-1].name,g.v[ends-1].name,dist[start-1][ends-1]);
                printf("%s->",g.v[start-1].name);
                Floyd_print(start-1, ends-1);
                printf("%s\n",g.v[ends-1].name);
            }
            else if(n==3)
            {
                Dis_map();
                counts=1;///起始路徑數為1
                printf("請輸入起點的景點:\n");
                scanf("%d",&start);
                printf("請輸入終點的景點:\n");
                scanf("%d",&ends);
                Dfs_allpath(start-1,ends-1);
            }
            else if(n==4)
            {
                Dis_map();
                Floyd();///弗洛伊德
                Bestpath_Multispot();
            }
            else if(n==5)
            {
                return 0;
            }
        }

    }
    return 0;
}

6 程序調試與測試

1)主菜單:

技術分享圖片

2)景點信息查詢

技術分享圖片

3)兩景點之間最短路徑查詢

技術分享圖片

4)兩景點之間所有路徑查詢

技術分享圖片

5)多景點間訪問路線查詢

技術分享圖片

數據結構實訓——校園導遊系統