数据结构课设—校园导游咨询
一.需求分析
-
任务分析
设计一个校园的导游图,为来访的客人进行景点信息的查询服务。包括对所有景点基本信息的查询,从一个景点到其他任意景点的最短路径的查询,还可以对景点按照评分进行排序输出。 -
功能分析
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;
}
}