//完整源代码
//2021/10/6
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Infinity 65535 //表示无穷大
#define MaxNumber 17 //用于邻接矩阵
#define vertex 13 //顶点个数
typedef struct side//边的权值
{
int wet;//权值
}side,wetmatrix[MaxNumber][MaxNumber];//边的邻接矩阵类型
typedef struct vetinf//顶点信息
{
int number;//顶点编号
char name[64];//顶点名称
char intro[256];//顶点介绍
}vetinf;
typedef struct mapstr//图结构信息
{
vetinf vets[MaxNumber];//顶点数组
wetmatrix mat;//邻接矩阵
int vetnum,sidenum;
}mapstr;
//全局变量
mapstr campus;//图结构变量(学校校园)
int d[30];
int visited[50];
int shortest[MaxNumber][MaxNumber];//定义全局变量存储最小路径
int pathh[MaxNumber][MaxNumber];//定义存储路径
//1.图的初始化
mapstr initmap()
{
mapstr m;//构件图m
int i=0,j=0;
m.vetnum=13;//定义顶点个数
m.sidenum=17;//义边的条数
for (i=1;i<=vertex;i++)//依次设置顶点信息
m.vets[i].number=i;
//输入顶点信息
strcpy(m.vets[1].name,"南门");strcpy(m.vets[1].intro,"位于学校最北端,学生出入的必经之地");
strcpy(m.vets[2].name,"图书馆");strcpy(m.vets[2].intro,"为工商学子提供舒适的学习环境");
strcpy(m.vets[3].name,"行政楼");strcpy(m.vets[3].intro,"为学校教职工提供优质的办公环境");
strcpy(m.vets[4].name,"实验楼");strcpy(m.vets[4].intro,"学生进行实验和项目实践的场所");
strcpy(m.vets[5].name,"教一楼");strcpy(m.vets[5].intro,"学生上课及学习的场所");
strcpy(m.vets[6].name,"教二楼");strcpy(m.vets[6].intro,"学生上课及学习的场所");
strcpy(m.vets[7].name,"食堂");strcpy(m.vets[7].intro,"有三大餐厅,为工商学子提供就餐场所");
strcpy(m.vets[8].name,"柳湾公寓");strcpy(m.vets[8].intro,"为学校学子提供适宜的生活环境");
strcpy(m.vets[9].name,"景槐公寓");strcpy(m.vets[9].intro,"为学校学子提供适宜的生活环境");
strcpy(m.vets[10].name,"北泉公寓");strcpy(m.vets[10].intro,"为学校学子提供适宜的生活环境");
strcpy(m.vets[11].name,"操场");strcpy(m.vets[11].intro,"方便广大教职工和学校学子进行运动和活动的场所,也用于举行校内活动");
strcpy(m.vets[12].name,"体育馆");strcpy(m.vets[12].intro,"这里方便学生进行运动和举行体育比赛");
strcpy(m.vets[13].name,"学生活动中心");strcpy(m.vets[13].intro,"用于拓展学生的课余生活,丰富学生的生活环境");
for (i=1;i<=vertex;i++)
for (j=1;j<=vertex;j++)
m.mat[i][j].wet=Infinity;//初始化图的邻接矩阵
m.mat[1][2].wet=133;m.mat[1][3].wet=100;m.mat[1][4].wet=98;m.mat[2][4].wet=87;m.mat[2][7].wet=120;
m.mat[2][5].wet=85;m.mat[3][5].wet=20;m.mat[5][6].wet=20;m.mat[6][8].wet=80;m.mat[7][8].wet=85;
m.mat[7][13].wet=87;m.mat[7][12].wet=180;m.mat[8][9].wet=40;m.mat[4][13].wet=120;m.mat[10][12].wet=85;
m.mat[11][13].wet=180;m.mat[11][12].wet=133;
for(i=1;i<=vertex;i++)//无向带权图是对称矩阵,给其另一半赋值
for(j=1;j<=vertex;j++)
m.mat[j][i].wet=m.mat[i][j].wet;
return m;
}
//2.查询景点在图中的序号
int locatevet(mapstr m,int v)
{
int i;
for(i=0;i<=m.vetnum;i++)
if(v==m.vets[i].number) return i;//找到返回顶点i
return -1;//未找到
}
//3.查询输入序号l,n间的长度不超过10个景点的路径
void path(mapstr m,int l,int n,int k)
{
int s,t=k+1;int length=0;//t用于存储路径上下一顶点对应的d[]数组元素的下标
if(d[k]==n&&k<8)//若d[k]是终点且景点个数<8,则输出该路径
{
for(s=0;s<k;s++)
{
length=length+m.mat[d[s]][d[s+1]].wet;
}
if(length<200)//打印路径小于200(定长)的路径
{
for(s=0;s<k;s++)//输出该路径,s=0时为起点m
{
printf("%d%s--->",d[s],m.vets[d[s]].name);
}
printf("%d%s ",d[s],m.vets[d[s]].name);//输出最后一个顶点
printf("总路线长为%d米\n\n",length);
}
}
else
{
s=1;
while(s<=m.vetnum)//从第m个顶点,访问所有顶点是否有路径
{
if((m.mat[d[k]][s].wet<Infinity)&&(visited[s]==0))//顶点有边且未被访问
{
visited[s]=1;
d[k+1]=s;//存储顶点编号
path(m,l,n,t);
visited[s]=0;//将找到的路径上的顶点的访问标志重新设置为,便于探究新的路径
}
s++;//试验下一顶点s开始是否有到终点的路径;
}
}
}
//4.查询两景点的所有路径
int allpath(mapstr m)
{
int k,i,j,l,n;
printf("\n\n请输入您想要查询的两个景点的编号:\n\n");
scanf("%d%d",&i,&j);printf("\n\n");
l=locatevet(m,i);//locatevet 确定该顶点是否存在。若存在,返回该顶点编号。
n=locatevet(m,j);
d[0]=l;//路径起点l(字母).(d[]数组为全局变量)
for(k=0;k<vertex;k++)
visited[k]=0;
visited[l]=1;
path(m,l,n,0);
return 1;
}
//5.迪杰斯特拉算法求单源最短路径
void shortestpath(mapstr m)
{
int v0,v,w,k=1,min,t,p;
int final[MaxNumber];//final[w]=1表示已经求得顶点V0到Vw的的最短路径
int Pathside[MaxNumber];//用于存储最短路径下标的数组
int ShortPathwet[MaxNumber];//用于存储到各点最短路径的权值和
printf("\n请输入起始景点的编号:");
scanf("%d",&v0);
printf("\n\n");
while(v0<0||v0>vertex)//判断是否输入正确
{
printf("\n您输入的景点编号不存在\n");
printf("请重新输入:");
scanf("%d",&v0);
}
for(v=1;v<=m.vetnum;v++)//数组初始化
{
final[v]=0;//全部顶点初始化为未找到路径
ShortPathwet[v]=m.mat[v0][v].wet;//将与v0有连线的路径加上权值
Pathside[v]=0;//初始化路径数组为0
}
ShortPathwet[v0]=0;
final[v0]=1;
//Dijkstr算法主体
for(v=1;v<=m.vetnum;v++)
{
min=Infinity;
for(w=1;w<=m.vetnum;w++)//找出离当前指向顶点最近的点
{
if(!final[w]&&ShortPathwet[w]<min)//未被访问且存在边
{
k=w;
min=ShortPathwet[w];
}
}
final[k]=1;//将找到的离当前顶点最近的置1
//修正
for(w=1;w<=m.vetnum;w++)
{
if(!final[w]&&(min+m.mat[k][w].wet<ShortPathwet[w]))
{
ShortPathwet[w]=min+m.mat[k][w].wet;//修改当前最优路径长度
Pathside[w]=k;//存放前驱结点
}
}
}
printf("打印P数组:"); //打印p数组
for(t=1;t<=m.vetnum;t++)
{
printf("%d ",Pathside[t]);
}
printf("\n\n");
printf("打印S数组:"); //打印s数组
for(t=1;t<=m.vetnum;t++)
{
printf("%d ",ShortPathwet[t]);
}
printf("\n\n");
//打印最短路径
for(t=1;t<=m.vetnum;t++)
{
p=t;
if(t!=v0)
{
printf("%d%s",t,m.vets[t].name);
for(w=1;w<=m.vetnum;w++)
{
if(Pathside[p]!=0)
{
printf("<--%d%s",Pathside[p],m.vets[p].name);
p=Pathside[p];
}
}
printf("<--%d%s",v0,m.vets[v0].name);
printf("\n总路线长为%d米\n\n",ShortPathwet[t]);
}
}
}
//6.主页
void menu()
{ printf(" ┌──────────────────────────────────────────────────────┐\n");
printf(" │ ╭ ═══════════════════════════════════════════════ ╮ │\n");
printf(" │ ││ 欢 迎 使 用 校 园 导 游 系 统 ││ │\n");
printf(" │ ╰ ═══════════════════════════════════════════════ ╯ │\n");
printf(" │ 欢迎来到 │\n");
printf(" │ 西安工商学院 │\n");
printf(" │ 菜 单 选 择 │\n");
printf(" │ *************************************************** │\n");
printf(" │ * 1.主页 ** 2.查看游览路线 * │\n");
printf(" │ *************************************************** │\n");
printf(" │ * 3.查询景点间最短路径 ** 4.查询景点间所有路径* │\n");
printf(" │ *************************************************** │\n");
printf(" │ * 5.学校景点介绍 ** 6.学校地图 * │\n");
printf(" │ *************************************************** │\n");
printf(" │ * 7.更改图信息 ** 0.退出 * │\n");
printf(" │ *************************************************** │\n");
printf(" └──────────────────────────────────────────────────────┘\n");
}
//以下是修改图的相关信息。
//7.重新构造图
int creatmap(mapstr *m)
{
int i,j,l,n,v0,v1,distance;
printf("请输入图的顶点数和边数:\n");
scanf("%d %d",&m->vetnum,&m->sidenum);
printf("请输入顶点信息: \n");
for(i=0;i<=m->vetnum;i++)//输入各顶点对应的景点信息
{
printf("请输入景点编号:");
scanf("%d",&m->vets[i].number);
printf("请输入景点名称:");
scanf("%s",&m->vets[i].name);
scanf("请输入景点简介:");
scanf("%s",&m->vets[i].intro);
}
for(i=0;i<=m->vetnum;i++)//权值初始化为无穷
for(j=0;j<=m->vetnum;j++)
m->mat[i][j].wet=Infinity;
printf("请输入图中各景点边的信息 \n");
for(i=1;i<=m->sidenum;i++)
{
printf("\n请输入第%d条边的起点,终点,长度为:",i);
scanf("%d %d %d",&v0,&v1,&distance);
l=locatevet(campus,v0);
n=locatevet(campus,v1);
if(l>0&&n>0)
{
m->mat[l][n].wet=distance;
m->mat[n][l].wet=m->mat[l][n].wet;
}
}
return 1;
}
//8.更改图部分信息
int newmap(mapstr *m)
{
int changenum,i,l,n,t,distance,v0,v1;
printf("\n下面请输入你要修改的景点的个数:\n");//修改定点对应的景点
scanf("%d",&changenum);
while(changenum<0||changenum>vertex)
{
printf("\n你的输入有误,请重新输入");
scanf("%d",&changenum);
}
for(i=0;i<changenum;i++)
{
printf("\n请输入景点编号:");
scanf("&d",&l);
t=locatevet(campus,l);
printf("\n请输入修改后景点的名称:");
scanf("%s",&m->vets[t].name);
printf("\n请输入修改后景点的简介:");
scanf("%s",&m->vets[t].intro);
}
printf("\n下面请输入你要修改的边的个数");
scanf("%d",&changenum);
while(changenum<0||changenum>vertex);
{
printf("\n你的输入有误,请重新输入");
scanf("%d",&changenum);
}
if(changenum!=0)
printf("\n下面请输入更新边的信息:\n");
for(i=1;i<=changenum;i++)
{
printf("\n修改的第%d条边的起点 终点 长度为:",i);
scanf("%d %d %d",&v0,&v1,&distance);
l=locatevet(campus,v0);
n=locatevet(campus,v1);
if(l>=0&&n>=0)
{
m->mat[l][n].wet=distance;
m->mat[n][l].wet=m->mat[l][n].wet;
}
}
return 1;
}
//9.增加一条边
int incside(mapstr *m)
{
int l,n,distance;
printf("\n请输入边的起点和终点编号,权值:");
scanf("%d%d%d",&l,&n,&distance);
while(l<0||l>m->vetnum||n<0||n>m->vetnum)
{
printf("输入错误,请重新输入");
scanf("%d %d",&l,&n);
}
if(locatevet(campus,l)<0)
{
printf("此节点%d已删除",l);
return 1;
}
if(locatevet(campus,n)<0)
{
printf("此节点%d已被删除",n);
return 1;
}
m->mat[l][n].wet=distance;
m->mat[n][l].wet=m->mat[l][n].wet;
m->sidenum ++;
return 1;
}
//10.增加一个结点
int incvet(mapstr *m)
{
int i;
m->vetnum++;//顶点数加一
printf("请输入您要增加结点的信息:");
printf("\n编号:");
scanf("%d",&m->vets[m->vetnum].number);
printf("名称:");
scanf("%s",&m->vets[m->vetnum].name);
printf("简介:");
scanf("%s",&m->vets[m->vetnum].intro);
for(i=1;i<=m->vetnum;i++)
{
m->mat[m->vetnum][i].wet=Infinity;
m->mat[i][m->vetnum].wet=Infinity;
}
return 1;
}
//11.删除一个结点
int delvet(mapstr *m)
{
int i=0,j,l,v;
if(m->vetnum<=0)
{
printf("图中已无顶点");
return 1;
}
printf("\n下面请输入您要删除的景点编号:");
scanf("%d",&v);
while(v<0||v>m->vetnum)
{
printf("\n输入错误!请重新输入:");
scanf("%d",&v);
}
l=locatevet(campus,v);
if(l<0)
{
printf("顶点%d已删除\n",v);
return 1;
}
for(i=l;i<=m->vetnum-1;i++)
for(j=1;j<=m->vetnum;j++)//将二维数组中的第m+1行依次向前移动一行(删除第m行)
m->mat[i][j]=m->mat[i+1][j];
for(i=l;i<=m->vetnum-1;i++)
for(j=1;j<=m->vetnum;j++)//将二维数组中的第m+1列依次向前移动一列(删除第m列)
m->mat[j][i]=m->mat[j][i+1];
m->vets[v].number=-1;//表示此点已删除,后期打印也不会显示该点
m->vetnum--;//顶点个数-1
return 1;
}
//12.删除一条边
int delside(mapstr *m)
{
int l,n,v0,v1;
if(m->vetnum<=0)
{
printf("图中没有边了,无法删除");
return 1;
}
printf("\n下面请输入您要删除的边的起点和终点编号:");
scanf("%d %d",&v0,&v1);
l=locatevet(campus,v0);
if(m<0)
{
printf("此%d顶点已删除",v0);
return 1;
}
n=locatevet(campus,v1);
if(n<0)
{
printf("此%d顶点已删除",v1);
return 1;
}
m->mat[l][n].wet=Infinity;//将删掉的边的权值改为无穷
m->mat[n][l].wet=Infinity;
m->sidenum--;//图的边数减一
return 1;
}
//13.输出图的邻接矩阵的值
void printmapstr(mapstr m)
{
int i,j,k=0;
for(i=1;i<=vertex;i++)
{
if(m.vets[i].number!=-1)
printf("%6d",i);
}
printf("\n");
for(i=1;i<=m.vetnum;i++)
{
for(j=1;j<=m.vetnum;j++)
{
if(m.mat[i][j].wet==Infinity)
printf(" **** ");
else
printf("%6d",m.mat[i][j].wet);
k++;
if(k%m.vetnum==0)
printf("\n");
}
}
}
//14.图的操作主函数
int changemap(mapstr *m)
{
int choice;
printf("(1)重新建图 (2)删除结点 (3)删除边\n");
printf("(4)增加结点 (5)增加边 (6)更新信息\n");
printf("(7)输出邻接矩阵 (8)返回主页 \n");
do
{
printf("请输入你的选择:");
scanf("%d",&choice);
switch(choice)
{
case 1:creatmap(m);break;
case 2:delvet(m);break;
case 3:delside(m);break;
case 4:incvet(m);break;
case 5:incside(m);break;
case 6:newmap(m);break;
case 7:printmapstr(campus);break;
case 8:system("cls");menu();return 1;
default:printf("未找到该功能,请输入有效选项!\n");break;
}
}while(choice);
}
//15.用户登录
int userlog()
{
int i;
int a[6]={1,2,3,4,5,6},b[6];
printf("\n请输入六位密码(用空格隔开):\n");
for(i=0;i<6;i++)
scanf("%d",&b[i]);
for(i=0;i<6;i++)
{
if(a[i]!=b[i])
{
printf("密码错误!自动返回主页面\n");
menu();
return 0;
}
}
printf("密码正确,登陆成功!\n\n");
changemap(&campus);
}
//16.弗洛伊德算法
void floyd(mapstr m)
{
int i,j,k;
for(i=1;i<=vertex;i++)//将图的邻接矩阵赋值给 shortest二维数组,将矩阵pathh全部初始化为-1
{
for(j=1;j<=vertex;j++)
{
shortest[i][j]=m.mat[i][j].wet;
pathh[i][j]=j;
}
}
int ii,jj,k1=0;
for(ii=1;ii<=vertex;ii++)
printf("%6d",ii);//横着标号1到11
printf("\n");
for(ii=1;ii<=vertex;ii++)
{
printf("%d",ii);
for(jj=1;jj<=vertex;jj++)
{
printf("%6d",pathh[ii][jj]);
k1++;
if(k1%vertex==0)
printf("\n");
}
}
printf("\n\n\n");
for(k=1;k<=vertex;k++)//核心操作,完成了以k为中间点对所有的顶点对(i,j)进行检测和修改
{ for(i=1;i<=vertex;i++)
{ for(j=1;j<=vertex;j++)
{
if(shortest[i][j]>shortest[i][k]+shortest[k][j])
{ shortest[i][j]=shortest[i][k]+shortest[k][j];
pathh[i][j]=pathh[i][k];//记录一下所走的路 //P数组用来存放前驱顶点
}
}
}
}
}
//17.输出数组
void printarray()
{
int i,j,k=0;
for(i=1;i<=vertex;i++)
printf("%6d",i);//横着标号0-11
printf("\n");
for(i=0;i<=vertex;i++)
{
printf("%d",i);//竖着标号0-11
for(j=1;j<=vertex;j++)
{
printf("%6d",pathh[i][j]);
k++;
if(k%vertex==0)
printf("\n");
}
}
printf("\n\n\n");
}
//18.输出最短路径
void display(mapstr m,int i,int j)
{
int a,b;
a=i,b=j;
printf("您要查询的两景点间最短路径:\n\n");
printf("%d%s",a,m.vets[a].name);
while(pathh[i][j]!=b)
{
printf("-->%d%s",pathh[i][j],m.vets[pathh[i][j]].name);
i=pathh[i][j];
}
printf("-->%d%s\n\n",b,m.vets[b].name);
printf("%s-->%s的最短路径是:%d米\n\n",m.vets[a].name,m.vets[b].name,shortest[a][b]);
}
//19任意两点间距离(16-19)
int shortdistance(mapstr m)
{
int i,j;
printf("请输入要查询的两个景点的数字编号(用空格隔开)\n");
scanf("%d %d",&i,&j);
if(i<0||i>vertex||j<0||j>vertex)
{
printf("输入信息有误!\n\n");
printf("请输入要查询的两个景点的数字编号(用空格隔开)\n");
scanf("%d %d",&i,&j);
}
else
{
floyd(m);
printarray();
display(m,i,j);
}
return 1;
}
//20显示所有景点信息
void compusinfor(mapstr m)
{
int i;
printf(" \n\n编号 景点名称 简介\n");
printf("*************************************************************************\n");
for(i=1;i<=vertex;i++)
{
if(m.vets[i].number!=-1)
printf("%-10d%-25s%-70s\n",m.vets[i].number,m.vets[i].name,m.vets[i].intro);
}
printf("*************************************************************************\n");
}
void schoolmap()
{
printf(" ---------------------------------西安工商学院地图----------------------------------------\n");
printf("```````````````````````````````````````1、南门````````````````````````````````````````````\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("````````````````````````````````````````````````````````````````````````````````````3、行政楼\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("4、实验楼`````````````````````````````````2、图书馆```````````````````````````````````````5、教一楼\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("````````````````````````````````````````````````````````````````````````````````````6、教二楼\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("13、学生活动中心``````````````````````````````7、食堂`````````````````````````````````````````8、柳湾公寓````9、景槐公寓\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("``````````````````````````````````````````````````````````````````````````````````````````\n");
printf("````````````````````````````````````````````````````````````````````````````````````10、北泉公寓\n");
printf("``````````````````````````````````````12、体育馆``````````````````````````````````````````````\n");
printf("11、操场```````````````````````````````````````````````````````````````````````````````````\n");
printf("\n\n");
printf("\n 西<---|--->东 \n");
}
//22用户界面
void mainwork()
{
menu();
int choice;
campus=initmap();
do
{
printf("请输入你的选择:");
scanf("%d",&choice);
switch(choice)
{
case 1:system("cls");menu();break;
case 2:system("cls");shortestpath(campus);break;
case 3:system("cls");shortdistance(campus);break;
case 4:system("cls");allpath(campus);break;
case 5:system("cls");compusinfor(campus);break;
case 6:system("cls");schoolmap();break;
case 7:system("cls");userlog();break;
case 0:system("cls");printf("谢谢使用\n");break;
default:printf("未找到该功能,请输入有效选项!\n");break;
}
}while(choice);
}
int main()
{
mainwork();
return 0;
}
09-21