C++實(shí)現(xiàn)景區(qū)旅游信息管理系統(tǒng)
本文實(shí)例為大家分享了C++實(shí)現(xiàn)景區(qū)旅游信息管理系統(tǒng)的具體代碼,供大家參考,具體內(nèi)容如下
1 問題描述
如今生活水平提高,大家都喜歡在假期中到一個(gè)旅游景點(diǎn)參觀,在旅游景區(qū)中經(jīng)常聽到游客打聽從一個(gè)景點(diǎn)到另一個(gè)景點(diǎn)的最短路徑和最短距離,這類不喜歡按照導(dǎo)游圖來游覽的游客常常需要一個(gè)景區(qū)管理系統(tǒng)來挑選自己喜歡的旅游景點(diǎn),再規(guī)劃一個(gè)最短路徑和最短距離來游覽,一邊節(jié)省時(shí)間跟提高旅游效率。
2 數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)
建立一個(gè)景區(qū)旅游信息管理系統(tǒng),實(shí)現(xiàn)如下功能:
1、創(chuàng)建景區(qū)景點(diǎn)分布圖
通過一個(gè)鄰接矩陣(實(shí)質(zhì)是一個(gè)二維數(shù)組,m[i][j]表示從i到j(luò)的權(quán)值大小,為零表示沒有直達(dá)的路徑)記錄景區(qū)景點(diǎn)的分布圖.
2、輸出景區(qū)景點(diǎn)分布圖(鄰接矩陣)
通過掃描鄰接矩陣輸出景區(qū)景點(diǎn)分布圖
3、輸出導(dǎo)游線路圖:深度優(yōu)先策略
首先通過遍歷景點(diǎn),通過用戶給出的一個(gè)入口景點(diǎn)c,建立一個(gè)導(dǎo)游線路圖,導(dǎo)游線路圖用有向圖表示。遍歷采用深度優(yōu)先策略(遞歸),這個(gè)也是正常的游客的心理
4、判斷導(dǎo)游線路圖有無(wú)回路:拓?fù)渑判颍ú檎胰攵却笥?的景點(diǎn))
為了使導(dǎo)游線路圖能夠優(yōu)化,可以通過拓?fù)渑判蚺袛鄨D中有無(wú)回路,若有回路則打印輸出回路中的景點(diǎn),供人工優(yōu)化
5、求兩個(gè)景點(diǎn)間的最短路徑和最短距離:floyd算法
在導(dǎo)游線路圖中,還為一些不愿按線路走的游客提供信息服務(wù),比如從一個(gè)景點(diǎn)到另一個(gè)景點(diǎn)的最短路徑和最短距離。在本線路圖中將輸出任意景點(diǎn)間的最短路徑和最短距離
6、輸出道路修建規(guī)劃圖:prime算法
在景區(qū)建設(shè)中,道路建設(shè)是其中一個(gè)重要的內(nèi)容。道路建設(shè)首先要保證能連通所有景點(diǎn),但又要花最小的代價(jià),可以通過求最小生成樹來解決這個(gè)問題,通過prime算法來求最小生成樹
通過修改后添加的功能:
7、將景區(qū)景點(diǎn)分布圖安裝指定的文件名(可以景區(qū)名字命名)保存到默認(rèn)的目錄file下
在這里我遇到了路徑格式問題,通過查詢資料得以解決這個(gè)問題
8、從默認(rèn)目錄file下讀取指定文件名的景區(qū)景點(diǎn)分布圖
這樣就減少了每次都要?jiǎng)?chuàng)建景區(qū)景點(diǎn)分布圖,也方便從已有的景區(qū)景點(diǎn)分布圖導(dǎo)入系統(tǒng),不用手動(dòng)新建,實(shí)際應(yīng)用中更加的方便人性化
9、為當(dāng)前的景區(qū)添加景點(diǎn)道路
一開始沒有將景區(qū)景點(diǎn)的路徑清零,以至于添加景點(diǎn)道路后,再?gòu)男聦?dǎo)入景點(diǎn)較少的景區(qū)景點(diǎn)分布圖,再添加景點(diǎn)道路的時(shí)候發(fā)現(xiàn)之前的道路依然存在,因此在添加景點(diǎn)道路之前要將道路景區(qū)清零
3 算法設(shè)計(jì)(核心代碼)
//深度優(yōu)先搜索導(dǎo)游線路 int visited[M]={0}; int np=0;//找到的景點(diǎn)個(gè)數(shù) int p[M];//表示各個(gè)景點(diǎn)的入度值 void DFS(int c){ ? ? //c為景點(diǎn)編號(hào) ? ? np++;//每遞歸調(diào)用一次就自加一次,作為判斷是否到了最后一個(gè)景點(diǎn) ? ? p[c]++; ? ? if(np==S.count){ ? ? ? ? //到了最后一個(gè)景點(diǎn) ? ? ? ? cout<<S.mat.Pname[c]<<endl; ? ? ? ? returnMainFace(); ? ? }else{ ? ? ? ?cout<<S.mat.Pname[c]<<"-->"; ? ? } ? ? ?visited[c]=1; ? ? ?for(int i=0;i<S.count;i++){ ? ? ? ? if(S.mat.m[c][i]>0&&visited[i]==0){ ? ? ? ? ? ? ?DFS(i); ? ? ? ? ? ? ?if(S.count>np){ ? ? ? ? ? ? ? ? ?cout<<S.mat.Pname[c]<<"-->"; ? ? ? ? ? ? ? ? ?p[c]++; ? ? ? ? ? ? ?} ? ? ? ? ?} ? ? ?} ? ? ?if(np==S.count) ? ? ? ? ?returnMainFace(); } void guide_line()//導(dǎo)游線路 { ? ? ?checked(); ? ? ?cout<<"\n*請(qǐng)輸入起始景點(diǎn)的景點(diǎn)編號(hào):"; ? ? ?int c; ? ? ?cin>>c; ? ? ?c--; ? ? ?for(int i=0;i<S.count;i++){ ? ? ? ? ?visited[i]=0; ? ? ? ? ?p[i]=0;//入度置初值為0 ? ? ?} ? ? ?np=0; ? ? ?cout<<"*形成的導(dǎo)游線路圖(采取深度優(yōu)先策略)如下所示:\n\n\t"; ? ? ?DFS(c); } //Floyd(佛洛依德)算法,A[M][M]表示最短距離,path[M][M]表示輔助數(shù)組,記住前驅(qū) void Floyd(int A[M][M],int path[M][M]){ ? ? ?int i,j,k; ? ? ?for(i=0;i<S.count;i++){ ? ? ? ? ?for(j=0;j<S.count;j++){ ? ? ? ? ? ? if(S.mat.m[i][j]==0&&i!=j){ ? ? ? ? ? ? ? ? ?//如果兩點(diǎn)之間沒有邊相連,則權(quán)為無(wú)窮大 ? ? ? ? ? ? ? ? ?A[i][j]=INF;//INF=999666333 ? ? ? ? ? ? ?}else if(i==j){ ? ? ? ? ? ? ? ? ?A[i][j]=0; ? ? ? ? ? ? ?}else{ ? ? ? ? ? ? ? ? ?//S.mat.m[i][j]表示兩個(gè)景點(diǎn)之間的道路長(zhǎng)度 ? ? ? ? ? ? ? ? A[i][j]=S.mat.m[i][j]; ? ? ? ? ? ? ?} ? ? ? ? ? ? ?//給所有的path[i][j]賦值 ? ? ? ? ? ? ?if(i!=j&&S.mat.m[i][j]<INF){ ? ? ? ? ? ? ? ? ?path[i][j]=i; ? ? ? ? ? ? ?}else{ ? ? ? ? ? ? ? ? ?//(i==j&&S.mat.m[i][j]=INF ? ? ? ? ? ? ? ? ?path[i][j]=-1; ? ? ? ? ? ? ?} ? ? ? ? ?} ? ? ?} ? ? ? ? //k注意放到最外層,讓A[i][j]檢測(cè)都經(jīng)過每一個(gè)k ? ? ? ? ?for(k=0;k<S.count;k++){ ? ? ? ? ? ? ?for(i=0;i<S.count;i++){ ? ? ? ? ? ? ? ? for(j=0;j<S.count;j++){ ? ? ? ? ? ? ? ? ? ? if(A[i][j]>A[i][k]+A[k][j]){//如果i->j的權(quán)值大于i->k->j的權(quán)值 ? ? ? ? ? ? ? ? ? ? ? ? A[i][j]=A[i][k]+A[k][j]; ? ? ? ? ? ? ? ? ? ? ? ? path[i][j]=path[k][j];//path[k][j]=k前驅(qū)?k是指向的下一個(gè)景點(diǎn) ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ?} ? ? ? ? ?} } void min_distance()//最短路徑、距離 { ? ? ?checked(); ? ? ?int A[M][M],path[M][M]; ? ? ?Floyd(A,path);//A是一個(gè)景點(diǎn)到另一個(gè)景點(diǎn)的最短路徑的長(zhǎng)度 ? ? ?while(true){ ? ? ? ? ?Num_Name();//編號(hào)對(duì)應(yīng)的景點(diǎn)名稱 ? ? ? ? ?int i,j,k,s; ? ? ? ? ?int apath[M],d;//apath[M]是記錄路徑的數(shù)組 ? ? ? ? ?bool flag=true; ? ? ? ? ?while(flag){ ? ? ? ? ? ? ?cout<<"\t-景點(diǎn)1:"; ? ? ? ? ? ? ?cin>>i; ? ? ? ? ? ? ?i--; ? ? ? ? ? ? if(i<0||i>S.count-1){ ? ? ? ? ? ? ? ? ?cout<<"*請(qǐng)輸入合法的景點(diǎn)編號(hào):\n"; ? ? ? ? ? ? ?}else{ ? ? ? ? ? ? ? ? ?flag=false; ? ? ? ? ? ? ?} ? ? ? ? ?} ? ? ? ? ?flag=true; ? ? ? ? ?while(flag){ ? ? ? ? ? ? ?cout<<"\t-景點(diǎn)2:"; ? ? ? ? ? ? ?cin>>j; ? ? ? ? ? ? ?j--; ? ? ? ? ? ? if(j<0||j>S.count-1){ ? ? ? ? ? ? ? ? ?cout<<"*請(qǐng)輸入合法的景點(diǎn)編號(hào):\n"; ? ? ? ? ? ? ?}else{ ? ? ? ? ? ? ? ? ?flag=false; ? ? ? ? ? ? ?} ? ? ? ? ?} ? ? ? ? if(A[i][j]<INF&&i!=j){ ? ? ? ? ? ? ?k=path[i][j];//k是指向的下一個(gè)景點(diǎn) ? ? ? ? ? ? ?d=0;//路徑有d+2個(gè)景點(diǎn),是數(shù)組apath的下標(biāo) ? ? ? ? ? ? ?//將待輸出的路徑的點(diǎn)存放在棧apath中 ? ? ? ? ? ? ?apath[d]=j;//最后一個(gè)景點(diǎn) ? ? ? ? ? ? while(k!=-1&&k!=i){ ? ? ? ? ? ? ? ? ?d++; ? ? ? ? ? ? ? ? ?apath[d]=k; ? ? ? ? ? ? ? ? ?//再繼續(xù)判斷還有沒有景點(diǎn) ? ? ? ? ? ? ? ? ?k=path[i][k]; ? ? ? ? ? ? ?} ? ? ? ? ? ? ?d++; ? ? ? ? ? ? ?apath[d]=i;//加上第一點(diǎn) ? ? ? ? ? ? ?cout<<"\n*從 "<<S.mat.Pname[i]<<" 到"<<S.mat.Pname[j]<<" 最短路徑為:"; ? ? ? ? ? ? ?cout<<S.mat.Pname[apath[d]];//apath[M]數(shù)組最后一個(gè),就是第一個(gè)起點(diǎn),相當(dāng)于棧 ? ? ? ? ? ? ?for(s=d-1;s>=0;s--){//將剩下的景點(diǎn)(apath[M]數(shù)組剩下的元素)打印出來 ? ? ? ? ? ? ? ? ?cout<<"-->"<<S.mat.Pname[apath[s]]; ? ? ? ? ? ? ?} ? ? ? ? ? ? ?cout<<" ,最短距離為:"<<A[i][j]<<endl;//Floyd算法已經(jīng)將最短路徑算出來存放到了A[i][j](將INF的值用最短路徑代替了) ? ? ? ? ?}else if(i==j){ ? ? ? ? ? ? ?cout<<"\n*景點(diǎn)輸入不合法,輸入的兩個(gè)景點(diǎn)不能相同!\n"; ? ? ? ? ?}else{ ? ? ? ? ? ? ?cout<<"\n*這兩個(gè)景點(diǎn)間不存在路徑\n"; ? ? ? ? ?} ? ? ? ? ?cout<<"\n是否繼續(xù)執(zhí)行最短路徑和最短距離的查詢(Y/N)"; ? ? ? ? ?Y_N(); ? ? ?} ? ? ?returnMainFace(); } //道路修建規(guī)劃圖、最小生成樹(prime算法) void build_road() { ? ? ?checked(); ? ? ?cout<<"\n*道路修建規(guī)劃圖(prime算法)規(guī)劃如下:\n"; ? ? ?//Ai[M]表示待選邊的權(quán)值,鄰接矩陣的一行,closest[M]:點(diǎn)編號(hào)數(shù)組,記錄下一條路的起點(diǎn)景點(diǎn)的編號(hào) ? ? ?intAi[M],min,closest[M],i,j,k,sum=0,num=0;//num表示第幾條路 ? ? ?int A[M][M]; ? ? ?//賦權(quán)值 ? ? ?for(i=0;i<S.count;i++){ ? ? ? ? ?for(j=0;j<S.count;j++){ ? ? ? ? ? ? if(S.mat.m[i][j]==0&&i!=j){ ? ? ? ? ? ? ? ? ?A[i][j]=INF; ? ? ? ? ? ? ?}else if(i==j){ ? ? ? ? ? ? ? ? ?A[i][j]=0; ? ? ? ? ? ? ?}else{ ? ? ? ? ? ? ? ? A[i][j]=S.mat.m[i][j]; ? ? ? ? ? ? ?} ? ? ? ? ?} ? ? ?} ? ? ?for(i=0;i<S.count;i++){ ? ? ? ? ?Ai[i]=A[0][i];//取第一行存四個(gè)Ai[i],就是一個(gè)景點(diǎn)到所有景點(diǎn)的權(quán)值 ? ? ? ? ?closest[i]=0;//0 ? ? ?} ? ? ?for(i=1;i<S.count;i++){ ? ? ? ? ?min=INF; ? ? ? ? ?//從Ai[j]中選出最小的值存放在min ? ? ? ? ?for(j=0;j<S.count;j++){ ? ? ? ? ? ? if(Ai[j]!=0&&Ai[j]<min){ ? ? ? ? ? ? ? ? ?min=Ai[j]; ? ? ? ? ? ? ? ? ?k=j;//記錄最小的值的列j:k=j,為了下面標(biāo)志此路已選 ? ? ? ? ? ? ?} ? ? ? ? ?} ? ? ? ? ?if(min<INF){ ? ? ? ? ? ? ?cout<<"\t-第 "<<++num<<" 條路: 從"<<S.mat.Pname[closest[k]]<<" 到"<<S.mat.Pname[k]<<" , 該道路長(zhǎng)度為:"<<min<<endl; ? ? ? ? ? ? ?sum+=min;//sum累計(jì)道路長(zhǎng)度,即是已選的權(quán)值 ? ? ? ? ?} ? ? ? ? ?Ai[k]=0;//標(biāo)志為已選的邊的權(quán)值,避免重復(fù)選擇 ? ? ? ? ?//例子:對(duì)比a到c和b到c的權(quán)值,取最小存進(jìn)Ai[j]中 ? ? ? ? ?for(j=0;j<S.count;j++){ ? ? ? ? ? ? if(A[k][j]!=0&&A[k][j]<Ai[j]){ ? ? ? ? ? ? ? ? ?Ai[j]=A[k][j]; ? ? ? ? ? ? ? ? ?closest[j]=k;//點(diǎn)編號(hào)數(shù)組,記錄下一條路的起點(diǎn)景點(diǎn)的編號(hào) ? ? ? ? ? ? ?} ? ? ? ? ?} ? ? ?} ? ? ?cout<<"*修建道路的總長(zhǎng)度為:"<<sum<<endl; ? ? ?returnMainFace(); }
4 運(yùn)行與測(cè)試
通過創(chuàng)建不同的景區(qū)景點(diǎn)分布圖來測(cè)試,測(cè)試結(jié)果正確無(wú)誤。
5 總結(jié)與心得
通過認(rèn)真對(duì)待數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì),認(rèn)真思考如何用算法和代碼來解決現(xiàn)實(shí)生活中的問題,認(rèn)真參考優(yōu)秀參考文獻(xiàn)和優(yōu)秀作品后,收獲甚多。一開始,面對(duì)現(xiàn)實(shí)生活的問題,毫無(wú)頭緒,不知如何入手來實(shí)現(xiàn)解決現(xiàn)實(shí)生活的問題,后來通過參考文獻(xiàn)和別人的類似作品后,才發(fā)現(xiàn)原來數(shù)據(jù)結(jié)構(gòu)算法是這樣使用的,也因此解開之前在上數(shù)據(jù)結(jié)構(gòu)課堂上的疑惑:數(shù)據(jù)結(jié)構(gòu)如何運(yùn)用在我們的工作代碼上??偟膩碚f,收獲的東西確實(shí)不少,只要認(rèn)真對(duì)待學(xué)習(xí)上的每一個(gè)環(huán)節(jié),就一定會(huì)有收獲。
通過老師的指導(dǎo),此系統(tǒng)優(yōu)化了很大哦,并且讓我學(xué)會(huì)了很多東西,很多實(shí)際問題都沒有考慮周全,老師都可以指出并要求我修改,正是因?yàn)樾薷模抛屛覍W(xué)到了更多的知識(shí),使我明白了,做課程設(shè)計(jì),不單單但是做課程設(shè)計(jì),還要通過這次課程設(shè)計(jì)來考慮實(shí)際問題,不斷優(yōu)化。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于C++詳解數(shù)據(jù)結(jié)構(gòu)(附帶例題)
數(shù)據(jù)結(jié)構(gòu)作為每一個(gè)IT人不可回避的問題,本文基于C++編寫,下面這篇文章主要給大家介紹了關(guān)于數(shù)據(jù)結(jié)構(gòu)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06C語(yǔ)言實(shí)現(xiàn)電影院選座管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)電影院選座管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12C++實(shí)現(xiàn)LeetCode(159.最多有兩個(gè)不同字符的最長(zhǎng)子串)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(159.最多有兩個(gè)不同字符的最長(zhǎng)子串),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07基于C語(yǔ)言實(shí)現(xiàn)鉆石棋游戲的示例代碼
獨(dú)立鉆石是源于18世紀(jì)法國(guó)的宮廷貴族的自我挑戰(zhàn)類單人棋游戲,可以鍛煉邏輯思維能力。本文將用C語(yǔ)言實(shí)現(xiàn)這一簡(jiǎn)單的游戲,感興趣的小伙伴可以了解一下2023-02-02C語(yǔ)言scandir函數(shù)獲取文件夾內(nèi)容的實(shí)現(xiàn)
scandir?函數(shù)用于列舉指定目錄下的文件列表,本文主要介紹了C語(yǔ)言scandir函數(shù)獲取文件夾內(nèi)容的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03用C語(yǔ)言遞歸實(shí)現(xiàn)火車調(diào)度算法詳解
本文主要介紹了用C語(yǔ)言遞歸實(shí)現(xiàn)火車調(diào)度算法詳解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11C語(yǔ)言控制臺(tái)應(yīng)用程序GDI繪制正弦曲線
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言控制臺(tái)應(yīng)用程序GDI繪制正弦曲線,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06C語(yǔ)言實(shí)現(xiàn)的統(tǒng)計(jì)php代碼行數(shù)功能源碼(支持文件夾、多目錄)
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)的統(tǒng)計(jì)php代碼行數(shù)功能源碼,支持文件夾、多級(jí)目錄的統(tǒng)計(jì),在一些環(huán)境中會(huì)用到這個(gè)功能,需要的朋友可以參考下2014-08-08