校园导游咨询--单源点最短路径的求解

数据结构课设—校园导游咨询

一.需求分析

  • 任务分析
    设计一个校园的导游图,为来访的客人进行景点信息的查询服务。包括对所有景点基本信息的查询,从一个景点到其他任意景点的最短路径的查询,还可以对景点按照评分进行排序输出。

  • 功能分析
    1.用图的数据结构对校园导游图的构建。
    2.用顺序查找对景点进行按照景点名进行信息查询。
    3.用折半查找对景点按照景点编号进行信息查询。
    4.用快速排序的方法对景点按照评分排序输出。
    5.用迪杰斯特拉算法进行从一个景点到另一个景点的最短路径查询。

  • 数据输入
    1.景点总数,景点路径总数;
    2.所有景点名,景点代号,景点评分,景点推荐语;
    3.路径两端的景点名的代号,进行创建图;
    注:实际上,由于景点名和景点路径过多,所以直接从文件中读取已定义的数据。
    文件内容为:
    在这里插入图片描述

  • 功能模块图:
    在这里插入图片描述

  • 抽象数据类型描述



ADT MGraph{

数据对象:

         具有相同特性的数据元素的集合,顶点集。

数据关系

           R={VR}

            VR={<v,w>|表示从顶点v到顶点w存在路径}

基本操作

Create_MGraph(MGraph &G);//创建图

       初始条件:G为空

       操作结果:创建完整的图

Output_MGraph(MGraph &G);//输出图

	初始条件:G为已创建好的图

       操作结果:输出图中顶点和边的信息

Dijkstra(MGraph G, int v0,int path[][MAX], int D[]);//求最短路径

       初始条件:G不为空

       操作结果:求出单源点到其他点的最短径路
       
  Find_Short_Path(MGraph G);//查询最短路径 

	初始条件:G不为空

       操作结果:输出单源点到查询点的最短路径

 Find_Short_AllPath(MGraphG);//查询所有的最短路径 

	初始条件:G不为空

       操作结果:输出单源点到其他点的最短路径 
       
 Find_scenery(MGraph G);//按照景色名称查询信息

	初始条件:G不为空

       操作结果:输出查询的景点信息
      
 Find_num(MGraph G);//按照编号查询相关信息 

	初始条件:G不为空

       操作结果:输出查询的景点信息
       
 Output_Score(MGraph&G);//按照评分排序

	初始条件:G不为空

       操作结果:输出按评分排序的景点

Fast_Partition(MGraph &G,int low,int high);//返回快排的最终位置

	初始条件:G不为空

       操作结果:返回每次快排的最终位置

Fast_Sort(MGraph &G,int low,int high);//用快排对景色按照评分排序

	初始条件:G不为空

       操作结果:对快排序列排序 

}


代码实现:

#include<iostream>
#include<fstream>
#include<istream>
#include<windows.h>
#include<string>
#include<iomanip>
#define MAX 15
#define INF 1000
using namespace std;
struct Node {
 string name;//景点名称
 int num;//代号
 int score;//评分 
 string recommend;//推荐语 
};//顶点 
struct AreCell {
 int adj;//该边是否存在
 int info;//该边的权值 
};//边 
struct MGraph {
 Node vex[MAX];//顶点数组 
 AreCell arcs[MAX][MAX];//邻接矩阵
 int  vex_num, arc_num;//顶点数,边数 
};//图  
void Create_MGraph(MGraph &G);//创建图
int Locate(MGraph G, int n);//辅助查找边代号 
int Locate(MGraph G, string s);//辅助查找景点名 
void Output_MGraph(MGraph &G);//输出图
void Dijkstra(MGraph G, int v0,int path[][MAX], int D[]);//求最短路径
void Find_Short_Path(MGraph G);//查询最短路径 
void Find_Short_AllPath(MGraph G);//查询所有的最短路径 
void Find_scenery(MGraph G);//按照景色名称查询信息
void Find_num(MGraph G);//按照编号查询相关信息 
void Output_Score(MGraph &G);//按照评分排序
int Fast_Partition(MGraph &G,int low,int high);//返回快排的最终位置
void Fast_Sort(MGraph &G,int low,int high);//用快排对景色按照评分排序 
void menu();//菜单 
int main() {
 menu();
 return 0;
}
int Locate(MGraph G, string s) {
 for (int i = 0; i<G.vex_num; i++)
  if (G.vex[i].name == s)
   return i;
 return 0;
}
int Locate(MGraph G, int n) {
 for (int i = 0; i<G.vex_num; i++)
  if (G.vex[i].num == n)
   return i;
 return 0;
}
void Create_MGraph(MGraph &G) {
 fstream file_read;
 file_read.open("1.txt",ios::in);
 if(!file_read)
  cout<<"文件打开失败!"<<endl;
 else{
  file_read>>G.vex_num>>G.arc_num;
  for (int i = 0; i<G.vex_num; i++)//构造顶点向量 
   file_read >> G.vex[i].name >> G.vex[i].num >> G.vex[i].score >> G.vex[i].recommend;
  for (int i = 0; i<G.vex_num; i++) {
   for (int j = 0; j<G.vex_num; j++) {
   G.arcs[i][j].adj = 0;//用0表示没有该边,用-1表示路径无穷远 
   G.arcs[i][j].info = INF;
   }
  }
  int n1, n2, w;
  for (int i = 0; i<G.arc_num; i++) {
   file_read >> n1 >> n2 >> w;
   int j1 = Locate(G, n1);
   int j2 = Locate(G, n2);
   G.arcs[j1][j2].adj = 1;
   G.arcs[j2][j1].adj = 1;
   G.arcs[j1][j2].info = w;
   G.arcs[j2][j1].info = w;
  }
  file_read.close();
 } 
}
void Output_MGraph(MGraph &G) {
 cout<<"景点总数为:"<<G.vex_num<<"  景点路径为:"<<G.arc_num<<endl<<endl; 
 cout << "输出各顶点的代号,景点名,评分,推荐语" << endl<<endl;
 for (int i = 0; i<G.vex_num; i++) {//输出顶点信息 
  cout << G.vex[i].num << "   " << G.vex[i].name << "   " << G.vex[i].score << endl;
  cout << G.vex[i].recommend << endl<<endl;
 }
 /*
 cout<<endl;
 for (int i = 0; i<G.vex_num; i++) {//输出边信息 
  for (int j = 0; j<G.vex_num; j++)
   cout << G.arcs[i][j].adj << "(" << G.arcs[i][j].info << ")" << " ";
  cout << endl;
 }
 */
}
void Dijkstra(MGraph G, int v0, int path[][MAX], int D[]){
 //final[vs]=1,表示v0到vs的最短路径已找到 
 //path[vs][v]=1,则v是:从v0到vs当前的最短路径上顶点的下标(存放vs之前的路径) 
 //D[vs],表示从v0到vs的最短路径的距离 
    int v, w, i, t; 
 int final[MAX];
 int min; 
 //初始化 
 for ( v = 0; v < G.vex_num; v++ ){
  final[v] = 0; 
  D[v] = G.arcs[v0][v].info;//最短路径为0 
  for ( w = 0; w < G.vex_num; w++ )
   path[v][w] = 0;
  if ( D[v] < INF ){ //存在v0到v到直达路径 
   path[v][v0] = 1;
   path[v][v] = 1;
  }
 }
 D[v0] = 0;          
 final[v0] = 1;
 for ( i = 1; i < G.vex_num; ++i ){//其余G.vexnum-1个顶点 
  min = INF; 
  for ( w = 0; w < G.vex_num; ++w )
   if ( !final[w] )// w顶点在v-s中 
    if ( D[w] < min ){//在v-s中找最短的距离 
     v = w;
     min = D[w];
    }
  final[v] = 1;                                                     
  for ( w = 0; w < G.vex_num; ++w )                         
   if ( !final[w] && ( (min + G.arcs[v][w].info) < D[w]) ){//和原来的比较,取小着 
    D[w] = min + G.arcs[v][w].info; 
          for ( t = 0; t < G.vex_num; t++ )
              path[w][t] = path[v][t];
    path[w][w] = 1;
   }
 }
}
void Find_Short_Path(MGraph G){
 string s1,s2;//起始点的编号
 int temp,i,j;
 int path[MAX][MAX]={0}, D[MAX]={0};
 cout << "输入起始点景点名称" << endl;
 cin >> s1;
 cout << "输入终点景点名称" << endl;
 cin >> s2;
 int v0 = Locate(G, s1);
 int vs = Locate(G, s2);
 Dijkstra(G, v0 ,path, D);
 if(vs!=v0){//终点!=起点 
  cout<<G.vex[v0].name<<"-到-"<<G.vex[vs].name<<"最短路径为:"<<endl;
  cout<<G.vex[v0].name;
  temp=v0;
  for(i=0;i<G.vex_num;i++){
   path[vs][v0]=0;
   for(j=0;j<G.vex_num;j++){//输出vs之前的路径 
    if(G.arcs[v0][j].info<INF&&path[vs][j]){//path[vs][j]==1
     cout<<"-->"<<G.vex[j].name;
     path[vs][j]=0;
     temp=j;//调整下个最短路径的节点 
    }
   } 
  }
  cout<<"-->"<<G.vex[vs].name<<" ,为: "<< D[vs]<<"米"<<endl<<endl;  
 }
}
void Find_Short_AllPath(MGraph G){
 string s1;//起始点的编号
 int temp,i,j;
 int path[MAX][MAX]={0}, D[MAX]={0};
 cout << "输入起始点景点名称" << endl;
 cin >> s1;
 int v0 = Locate(G, s1);
 Dijkstra(G, v0 ,path, D);
 for(int k=0;k<G.vex_num;k++){
  cout<<G.vex[v0].name<<"-到-"<<G.vex[k].name<<"最短路径为: ";
  cout<<G.vex[v0].name;
  temp=v0;
  for(i=0;i<G.vex_num;i++){//输出过程中的路径 
   path[k][v0]=0;
   for(j=0;j<G.vex_num;j++){
    if(G.arcs[v0][j].info<INF&&path[k][j]){
     cout<<"-->"<<G.vex[j].name;
     path[k][j]=0;
     temp=j;
    }
   } 
  }
  cout<<"-->"<<G.vex[k].name<<" ,为: "<< D[k]<<"米"<<endl<<endl;  
 }
}
void Find_scenery(MGraph G){//用顺序查找的方法 
 string s;
 int i;
 cout<<"请您输入要查询的景色名称"<<endl;
 cin>>s;
 for(i=G.vex_num-1;i>=0&&s!=G.vex[i].name;i--);
 if(i<0)
  cout<<"查无此景点!"<<endl;
 else{
  cout<<"景色名:"<<G.vex[i].name<<"  编号:"<<G.vex[i].num<<"    "<<"评分:"<<G.vex[i].score<<endl;
  cout<<"推荐语:"<<G.vex[i].recommend<<endl<<endl;
 } 
}
void Find_num(MGraph G){
 int n,k;
 cout<<"请您输入要查找的编号信息"<<endl;
 cin>>n;
 int low=0,high=G.vex_num;
 while(low<=high){
  int mid=(low+high)/2;
  if(G.vex[mid].num==n) {
   k=mid;
   break;
  }
  else if(mid<n) low=mid+1;
  else high=mid-1;
 }
 if(k<0||k>=G.vex_num)
  cout<<"查无此景点编号!"<<endl;
 else{
  cout<<"景色名:"<<G.vex[k].name<<"  编号:"<<G.vex[k].num<<"    "<<"评分:"<<G.vex[k].score<<endl;
  cout<<"推荐语:"<<G.vex[k].recommend<<endl<<endl;  
 }
}
int Fast_Partition(MGraph &G,int low,int high){
 int temp=G.vex[low].score;
 string s=G.vex[low].name;
 while(low<high){
  while(low<high&&G.vex[high].score>=temp)
   high--;
  G.vex[low].name=G.vex[high].name;
  G.vex[low].score=G.vex[high].score;
  while(low<high&&G.vex[low].score<=temp)
   low++;
  G.vex[high].name=G.vex[low].name;
  G.vex[high].score=G.vex[low].score;
 }
 G.vex[low].score=temp;
 G.vex[low].name=s;
 return low;
}
void Fast_Sort(MGraph &G,int low,int high){
 if(low<high){
  int flag=Fast_Partition(G,low,high);
  Fast_Sort(G,low,flag-1);
  Fast_Sort(G,flag+1,high);
 }
}
void Output_Score(MGraph &G){
 Fast_Sort(G,0,G.vex_num-1);
 for(int i=G.vex_num-1;i>=0;i--){//<<setfill(' ')
  cout<<"景色名:";
  cout<<left<<setw(19)<<G.vex[i].name<<"评分:"<<G.vex[i].score<<endl;
 }
  
}
void menu(){
 MGraph G;
 Create_MGraph(G);
 int n;
 cout<<"\n\n\n"<<endl;
 cout<<"\t\t\t\t"<<"*************北京建筑大学导购图************"<<endl;
 cout<<"\t\t\t\t\t"<<"浏览全部景点----------------1"<<endl; 
 cout<<"\t\t\t\t\t"<<"查看全部路径----------------2"<<endl;
 cout<<"\t\t\t\t\t"<<"查看评分景色----------------3"<<endl; 
 cout<<"\t\t\t\t\t"<<"查询最短路径----------------4"<<endl;
 cout<<"\t\t\t\t\t"<<"按景色名查询景色信息--------5"<<endl;
 cout<<"\t\t\t\t\t"<<"按编号查询景色信息----------6"<<endl;
 cout<<"\t\t\t\t\t"<<"退出------------------------0"<<endl; 
 cout<<"请您输入操作的编号"<<endl;
 cin>>n;
 switch(n){
  case 0:
   system("cls");
   cout<<"拜拜"<<endl; 
   break;
  case 1:
   Output_MGraph(G);
   system("pause");
   system("cls");
   menu();
   break;
  case 2:
   Find_Short_AllPath(G);
   system("pause");
   system("cls");
   menu();
   break;
  case 3:
   Output_Score(G);
   system("pause");
   system("cls");
   menu();
   break;
  case 4:
   Find_Short_Path(G);
   system("pause");
   system("cls");
   menu();
   break;
  case 5:
   Find_scenery(G);
   system("pause");
   system("cls");
   menu();
   break;
  case 6:
   Find_num(G);
   system("pause");
   system("cls");
   menu();
   break;
  default:
   cout<<"请输入正确的编号"<<endl;
   Sleep(1000);
   system("cls");
   menu();
   break;
 }
 
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值