该题目为郑州轻工业大学数据结构实验四的一道算法实验题,仅分享LZ的思路,代码提供参考
根据郑州市方特欢乐主题公园设计一个简单的游玩路线,设计数据结构和算法实现相应功能。要求所含景点不少于8个(方特城堡为其中一个景点,其他的例如极地快车、海螺湾、恐龙岛等)。以图中顶点表示公园内各景点,包含景点名称、景点介绍等信息;以边表示路径,存放路径长度信息。要求:
(1)根据上述信息创建一个图,使用邻接矩阵存储;
(2)景点信息查询:为游玩客人提供公园内任意景点相关信息的介绍;
(3)问路查询:为游玩客人提供从极地快车到达任意其它景点之间的一条最短路径。
选取A1极地快车-B2聊斋-C3熊大汉堡 -D4欢乐天地-E5方特城堡- F6恐龙园-G7海螺湾- H8唐古拉餐厅该八个景点,假设每个景点的距离为1km,草图如上,由图可知,该八个景点之间有10条路,已经编好号码,根据该图可得邻接矩阵该八个地点之间有十条路分别由以下两个景点编号相连
//2 1//3 2//4 3//5 3//5 4//6 5//7 6//8 1//8 2 //8 7
可得其邻接矩阵为:
//A B C D E F G H
//A 0 1 0 0 0 0 0 1
//B 1 0 1 0 0 0 0 1
//C 0 1 0 1 1 0 0 0
//D 0 0 1 0 1 0 0 0
//E 0 0 1 1 0 1 0 0
//F 0 0 0 0 1 0 1 0
//G 0 0 0 0 0 1 0 1
//H 1 1 0 0 0 0 1 0
该题目需要邻接矩阵的创建,队列的创建入队和出队,图的构建等函数,以下为LZ的代码思路
typedef struct MGraph {
char *vex[MAXSIZE]={"无","极地快车","聊斋","熊大汉堡","欢乐天地","方特城堡","恐龙园","海螺湾","唐古拉餐厅"}; //定义顶点数组,储存景点名称信息
char *intro[MAXSIZE]={"无","极地快车-根据艾尔斯伯格的同名冒险童话改编,讲述了小男孩克劳斯在圣诞节前夜,坐上特快列车和他的朋友去极地拜访传说中的圣诞老人的故事","聊斋-揭露封建统治的黑暗,或者抨击科举制度的腐朽,或者反抗封建礼教的束缚,具有丰富深刻的思想内容","熊大汉堡-熊大的汉堡餐厅","欢乐天地-KTV","方特城堡-游乐园","恐龙园-恐龙居住的地方","海螺湾-其以神奇的海底世界为故事背景,采用国际化的创意设计理念,构思新颖独特。这部制作精良的原创长篇动画精品","唐古拉餐厅-堂食餐厅"}; // 定义数组存储顶点介绍信息
int edge[MAXSIZE][MAXSIZE]; //定义边数组,储存边关系
int vexNum, edgeNum; //当前图中的顶点数、边数
}MGraph;
MGraph G;全局变量
typedef struct Queue{
int data[10];//空指针
int front,rear;
}Queue;
Queue Q;//全局变量
void InitQueue(Queue &Q){
Q.front = 0;
Q.rear = 0;
}
void EnQueue(Queue &Q, int e){//入队
if((Q.rear + 1) % MAXSIZE == Q.front){
printf("队满");
}else{
Q.data[Q.rear] = e; //将元素e赋值给队尾
Q.rear = (Q.rear + 1) % MAXSIZE; //rear指针向后移一位置,若到最后则转到数组头部
}
}
int DeQueue(Queue &Q, int e){//出队
if(Q.front==Q.rear){
printf("队空"); //队列空的判断
}else{
e = Q.data[Q.front]; //将队头元素赋值给e
Q.front = (Q.front + 1) % MAXSIZE; //front指针向后移一位置,若到最后则转到数组头部
return e;
}
}
该代码有一个我不知道的不影响编译的错误,是指针的一些问题
邻接矩阵的创建函数
//创建公园景点图
void CreatMGraph(MGraph& G) {
int i, j, k;
G.vexNum=8;
G.edgeNum=10;
for (i = 1; i <= G.vexNum; i++) {
for (j = 1; j <= G.vexNum; j++) {
G.edge[i][j] = 0;
//初始化邻接矩阵的元素为0
}
}
printf("请输入邻接顶点的下标:\n");
for (k = 1; k <=G.edgeNum; k++) {
scanf("%d %d", &i, &j);
G.edge[i][j] = 1; //将边关系录入数组
G.edge[j][i] = G.edge[i][j]; //对称矩阵
}
// int n=0;
// for (i = 1; i <= G.vexNum; i++) {
// for (j = 1; j <= G.vexNum; j++) {
// n++;
// printf(" %d",G.edge[i][j]);
// if(n%8==0){
// printf("\n\n");
// }
// }
// }//验证构建的图的正确性
}
然后是第一个功能查询景点的功能
void intro_park(MGraph *G){
printf("\n");
printf("请输入你要查询的景点名称的编号: ");
int n;
scanf("%d",&n);
for(int i=1;i<=8;i++){
if(i==n){
printf("该景点为:%s,",G->vex[i]);//景点的介绍和景点名称已经在变量G中存储,直接调用即可
printf("景点介绍:%s",G->intro[i]);
printf("\n");
printf("\n");
break;
}
}
}
接下来就是第二个功能,因为是所求一个固定景点到任意一个景点的最短距离,BFS算法再适合不过,不过由于需要用到FirstNeighbor(G,u)和NextNeighbor(G,u,w)。这两个函数书上没写具体算法,我自己编出来的能够使用,但是总感觉有些问题。我分享出来就是希望有大佬能改进或者其他好的思路
int FirstNeighbor(MGraph G,int u){//找第一个邻接点
for(int i=1;i<=G.vexNum;i++){
if(G.edge[u][i]==1)
return i;
}
return -1;//表示没有第一个邻接点
}
int NextNeighbor(MGraph G ,int u,int w){ //找第二个或第N个邻接点
int i=w;
for(i=w;i<=G.vexNum;i++){
if(G.edge[u][i]==1&&i!=w){
return i;//找到对应的内容,就结束循环
}
}
if(i==(G.vexNum+1)){//刚好是最后一个邻接点
return -1;
}
}
BFS代码很好写
//BFS算法求解非带权图单源最短路径问题
void BFS(MGraph G,int u){
int w;
for(int i = 1;i <=G.vexNum;i++){
d[i] = 9999;
path[i] = -1;
visited[i]=false;
}
d[u] = 0;
visited[u] = true;
EnQueue(Q,u);
while(Q.front!=Q.rear){
u=DeQueue(Q,u);
for(w = FirstNeighbor(G,u);w >= 0;w = NextNeighbor(G,u,w)){
if(!visited[w]){
d[w] = d[u] + 1;
path[w] = u;
visited[w] = true;
EnQueue(Q,w);
}
}
}
但BFS算法只求出了d[9],path[9]的需要存储的数值,学习过的同学肯定知道path数组的大用处
通过递归函数可以得到最短路径
void print(int x){
if(path[x]==-1){
printf("%s",G.vex[x]);
}else{
print(path[x]);
printf("->");
printf("%s",G.vex[x]);
}
}
select_park(MGraph *G,int d[],int path[]){
printf("\n");
printf("\t\t\t ........1极地快车-2聊斋-3熊大汉堡-4欢乐天地\t\................\n");
printf("\t\t\t ........5方特城堡-6恐龙园-7海螺湾-8唐古拉餐厅\t\................\n");
printf("请输入你要查询的景点编号:");
char order=getch();
switch(order){
case '1':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[1],d[1]);
printf("\n");
break;
case '2':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[2],d[2]);
print(2);//递归函数得到最短路径
printf("\n");
break;
case '3':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[3],d[3]);
print(3);
printf("\n");
break;
case '4':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[4],d[4]);
print(4);
printf("\n");
break;
case '5':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[5],d[5]);
print(5);
printf("\n");
break;
case '6':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[6],d[6]);
print(6);
printf("\n");
break;
case '7':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[7],d[7]);
print(7);
printf("\n");
break;
case '8':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[8],d[8]);
print(8);
printf("\n");
break;
}
}
最后主函数
int main(){
int u=1;
int flag=2;
InitQueue(Q);
CreatMGraph(G);
BFS(G,u);
while(flag>=0){
int i;
printf("\t\t\t=======================================================================\n");
printf("\t\t\t**********************┍ ------------------------┑ *********************\n");
printf("\t\t\t********************** 欢迎使用景点信息管理系统 *********************\n");
printf("\t\t\t**********************┕-------------------------┙ *********************\n");
printf("\t\t\txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx菜单xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
printf("\t\t\t=======================================================================\n");
printf("\t\t\t ........1极地快车-2聊斋-3熊大汉堡-4欢乐天地\t\..........\n");
printf("\t\t\t ........5方特城堡-6恐龙园-7海螺湾-8唐古拉餐厅\t........\n");
printf("\n");
printf("\t\t\t........... 1.景点信息查询 ..... 2.问路查询........\n");
printf("\t\t\t ............ 3.退出系统 ........... \n");
printf("输入数字选择功能: ");
char order=getch();
switch(order){
case '1':
intro_park(&G);
break;
case '2':
select_park(&G,d,path);
break;
case '3':
exit(0);//退出
printf("退出成功\n");
break;
}
}
return 0;
}
作业今天11.27日截止,希望各位复制代码的时候改个函数名字,改一些景点,把矩阵改成不一样的
//2 1//3 2//4 3//5 3//5 4//6 5//7 6//8 1//8 2 //8 7,数字代表两个景点,比如2 1代表A1极地快车和B2聊斋有一条路径,改变其他景点后这些数字要改变,八个景点有几条路径就有几组这样的数据
编译运行后后需要竖着输入以上10组数字
//完整代码
#include
#include
#include
#define MAXSIZE 100
#define INF 9999
//A极地快车-B聊斋-C熊大汉堡 -D欢乐天地-E方特城堡- F恐龙园-G海螺湾- H唐古拉餐厅
//数组第一个空间不使用
int visited[9];//这八个地区是否被访问过的标记
int d[9];
int path[9];//
//图结构
//邻接矩阵
// A B C D E F G H
//A 0 1 0 0 0 0 0 1
//B 1 0 1 0 0 0 0 1
//C 0 1 0 1 1 0 0 0
//D 0 0 1 0 1 0 0 0
//E 0 0 1 1 0 1 0 0
//F 0 0 0 0 1 0 1 0
//G 0 0 0 0 0 1 0 1
//H 1 1 0 0 0 0 1 0
typedef struct MGraph {
char *vex[MAXSIZE]={"无","极地快车","聊斋","熊大汉堡","欢乐天地","方特城堡","恐龙园","海螺湾","唐古拉餐厅"}; //定义顶点数组,储存景点名称信息
char *intro[MAXSIZE]={"无","极地快车-根据艾尔斯伯格的同名冒险童话改编,讲述了小男孩克劳斯在圣诞节前夜,坐上特快列车和他的朋友去极地拜访传说中的圣诞老人的故事","聊斋-揭露封建统治的黑暗,或者抨击科举制度的腐朽,或者反抗封建礼教的束缚,具有丰富深刻的思想内容","熊大汉堡-熊大的汉堡餐厅","欢乐天地-KTV","方特城堡-游乐园","恐龙园-恐龙居住的地方","海螺湾-其以神奇的海底世界为故事背景,采用国际化的创意设计理念,构思新颖独特。这部制作精良的原创长篇动画精品","唐古拉餐厅-堂食餐厅"}; // 定义数组存储顶点介绍信息
int edge[MAXSIZE][MAXSIZE]; //定义边数组,储存边关系
int vexNum, edgeNum; //当前图中的顶点数、边数
}MGraph;
MGraph G;
typedef struct Queue{
int data[10];//空指针
int front,rear;
}Queue;
Queue Q;
void InitQueue(Queue &Q){
Q.front = 0;
Q.rear = 0;
}
void EnQueue(Queue &Q, int e){//入队
if((Q.rear + 1) % MAXSIZE == Q.front){
printf("队满");
}else{
Q.data[Q.rear] = e; //将元素e赋值给队尾
Q.rear = (Q.rear + 1) % MAXSIZE; //rear指针向后移一位置,若到最后则转到数组头部
}
}
int DeQueue(Queue &Q, int e){//出队
if(Q.front==Q.rear){
printf("队空"); //队列空的判断
}else{
e = Q.data[Q.front]; //将队头元素赋值给e
Q.front = (Q.front + 1) % MAXSIZE; //front指针向后移一位置,若到最后则转到数组头部
return e;
}
}
int FirstNeighbor(MGraph G,int u){//找第一个邻接点
for(int i=1;i<=G.vexNum;i++){
if(G.edge[u][i]==1)
return i;
}
return -1;//表示没有第一个邻接点
}
int NextNeighbor(MGraph G ,int u,int w){ //找第二个或第N个邻接点
int i=w;
for(i=w;i<=G.vexNum;i++){
if(G.edge[u][i]==1&&i!=w){
return i;//找到对应的内容,就结束循环
}
}
if(i==(G.vexNum+1)){//刚好是最后一个邻接点
return -1;
}
}
void print(int x){
if(path[x]==-1){
printf("%s",G.vex[x]);
}else{
print(path[x]);
printf("->");
printf("%s",G.vex[x]);
}
}
//创建公园景点图
void CreatMGraph(MGraph& G) {
int i, j, k;
G.vexNum=8;
G.edgeNum=10;
for (i = 1; i <= G.vexNum; i++) {
for (j = 1; j <= G.vexNum; j++) {
G.edge[i][j] = 0;
//初始化邻接矩阵的元素为0
}
}
printf("请输入邻接顶点的下标:\n");
for (k = 1; k <=G.edgeNum; k++) {
scanf("%d %d", &i, &j);
G.edge[i][j] = 1; //将边关系录入数组
G.edge[j][i] = G.edge[i][j]; //对称矩阵
}
// int n=0;
// for (i = 1; i <= G.vexNum; i++) {
// for (j = 1; j <= G.vexNum; j++) {
// n++;
// printf(" %d",G.edge[i][j]);
// if(n%8==0){
// printf("\n\n");
// }
// }
// }//验证构建的图的正确性
}
//景点查询
void intro_park(MGraph *G){
printf("\n");
printf("请输入你要查询的景点名称的编号: ");
int n;
scanf("%d",&n);
for(int i=1;i<=8;i++){
if(i==n){
printf("该景点为:%s,",G->vex[i]);
printf("景点介绍:%s",G->intro[i]);
printf("\n");
printf("\n");
break;
}
}
}
select_park(MGraph *G,int d[],int path[]){
printf("\n");
printf("\t\t\t ........1极地快车-2聊斋-3熊大汉堡-4欢乐天地\t\................\n");
printf("\t\t\t ........5方特城堡-6恐龙园-7海螺湾-8唐古拉餐厅\t\................\n");
printf("请输入你要查询的景点编号:");
char order=getch();
switch(order){
case '1':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[1],d[1]);
printf("\n");
break;
case '2':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[2],d[2]);
print(2);
printf("\n");
break;
case '3':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[3],d[3]);
print(3);
printf("\n");
break;
case '4':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[4],d[4]);
print(4);
printf("\n");
break;
case '5':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[5],d[5]);
print(5);
printf("\n");
break;
case '6':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[6],d[6]);
print(6);
printf("\n");
break;
case '7':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[7],d[7]);
print(7);
printf("\n");
break;
case '8':
printf("\n");
printf("极地快车距离%s为%dkm,最短路径为:",G->vex[8],d[8]);
print(8);
printf("\n");
break;
}
}
//BFS算法求解非带权图单源最短路径问题
void BFS(MGraph G,int u){
int w;
for(int i = 1;i <=G.vexNum;i++){
d[i] = 9999;
path[i] = -1;
visited[i]=false;
}
d[u] = 0;
visited[u] = true;
EnQueue(Q,u);
while(Q.front!=Q.rear){
u=DeQueue(Q,u);
for(w = FirstNeighbor(G,u);w >= 0;w = NextNeighbor(G,u,w)){
if(!visited[w]){
d[w] = d[u] + 1;
path[w] = u;
visited[w] = true;
EnQueue(Q,w);
}
}
}
}
int main(){
int u=1;
int flag=2;
InitQueue(Q);
CreatMGraph(G);
BFS(G,u);
while(flag>=0){
int i;
printf("\t\t\t=======================================================================\n");
printf("\t\t\t**********************┍ ------------------------┑ *********************\n");
printf("\t\t\t********************** 欢迎使用景点信息管理系统 *********************\n");
printf("\t\t\t**********************┕-------------------------┙ *********************\n");
printf("\t\t\txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx菜单xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
printf("\t\t\t=======================================================================\n");
printf("\t\t\t ........1极地快车-2聊斋-3熊大汉堡-4欢乐天地\t\..........\n");
printf("\t\t\t ........5方特城堡-6恐龙园-7海螺湾-8唐古拉餐厅\t........\n");
printf("\n");
printf("\t\t\t........... 1.景点信息查询 ..... 2.问路查询........\n");
printf("\t\t\t ............ 3.退出系统 ........... \n");
printf("输入数字选择功能: ");
char order=getch();
switch(order){
case '1':
intro_park(&G);
break;
case '2':
select_park(&G,d,path);
break;
case '3':
exit(0);//退出
printf("退出成功\n");
break;
}
}
return 0;
}