只需实现创建线路和查询线路和修改站点三个功能,用创建邻接表并深度优先遍历编写
先上结果:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//2023年6月16日10:21:11
//定义邻接表结点
typedef struct node {
int dest; //目的站点编号
char name[20]; //站点名称
struct node *next; //指向下一个结点
} Node;
//定义邻接表头结点
typedef struct head {
int src; //起始站点编号
Node *first; //指向第一个邻接结点
} Head;
//定义公交线路结构体
typedef struct line {
int num; //线路编号
int count; //站点数量
Head *array; //邻接表数组
} Line;
//创建一个新的邻接结点
Node *newNode(int dest, char *name) {
Node *temp = (Node *)malloc(sizeof(Node));
temp->dest = dest;
strcpy(temp->name, name);
temp->next = NULL;
return temp;
}
//创建一个新的公交线路
Line *createLine(int num, int count) {
Line *line = (Line *)malloc(sizeof(Line));
line->num = num;
line->count = count;
line->array = (Head *)malloc(count * sizeof(Head));
for (int i = 0; i < count; i++) {
line->array[i].src = i;
line->array[i].first = NULL;
}
return line;
}
//添加一个新的站点到公交线路中
void addStation(Line *line, int src, int dest, char *name) {
Node *temp = newNode(dest, name);
temp->next = line->array[src].first;
line->array[src].first = temp;
}
//打印公交线路信息
void printLine(Line *line) {
printf("线路%d:\n", line->num);
for (int i = 0; i < line->count; i++) {
printf("%d: ", line->array[i].src);
Node *p = line->array[i].first;
while (p) {
printf("%d(%s) ", p->dest, p->name);
p = p->next;
}
printf("\n");
}
}
//深度优先遍历公交线路
void dfs(Line *line, int src, int visited[]) {
visited[src] = 1; //标记当前站点已访问
printf("%d(%s) ", src, line->array[src].first->name); //打印当前站点信息
Node *p = line->array[src].first;
while (p) {
if (!visited[p->dest]) { //如果邻接站点未访问,递归遍历
dfs(line, p->dest, visited);
}
p = p->next;
}
}
//查询公交线路信息
void queryLine(Line *line) {
int src; //起始站点编号
printf("请输入要查询的起始站点编号:");
scanf("%d", &src);
if (src < 0 || src >= line->count) { //检查输入是否合法
printf("输入错误,站点编号不存在。\n");
return;
}
int visited[line->count]; //记录每个站点是否访问过的数组
memset(visited, 0, sizeof(visited)); //初始化为0,表示未访问过
printf("从%d号站点出发,可以到达以下站点:\n", src);
dfs(line, src, visited); //深度优先遍历公交线路
printf("\n");
}
//创建公交线路信息
void createLine(Line *line) {
//创建线路的功能
int num, count; //新的线路编号和站点数量
printf("请输入新的线路编号和站点数量:");
scanf("%d %d", &num, &count);
Line *newLine = createLine(num, count); //创建一个新的公交线路
for (int i = 0; i < count; i++) { //循环添加站点到公交线路中
int src, dest; //起始站点编号和目的站点编号
char name[20]; //站点名称
printf("请输入第%d个站点的邻接站点编号和名称(-1表示结束):", i);
scanf("%d %s", &dest, name);
while (dest != -1) { //当输入-1时结束输入
addStation(newLine, i, dest, name); //添加一个新的站点到公交线路中
scanf("%d %s", &dest, name); //继续输入下一个邻接站点
}
}
//将新创建的公交线路保存到一个数组或链表中,这里为了简单,直接替换原来的线路
line = newLine;
printf("创建成功。\n");
}
//修改公交线路中的站点名称
void modifyStation(Line *line) {
int src, dest; //起始站点编号和目的站点编号
char name[20]; //新的站点名称
printf("请输入要修改的起始站点编号和目的站点编号:");
scanf("%d %d", &src, &dest);
if (src < 0 || src >= line->count || dest < 0 || dest >= line->count) { //检查输入是否合法
printf("输入错误,站点编号不存在。\n");
return;
}
Node *p = line->array[src].first;
while (p) {
if (p->dest == dest) { //找到要修改的站点
printf("请输入新的站点名称:");
scanf("%s", name);
strcpy(p->name, name); //修改站点名称
printf("修改成功。\n");
return;
}
p = p->next;
}
printf("修改失败,站点不存在。\n");
}
//主函数
int main() {
//创建一个公交线路
Line *line = createLine(1, 5);
//添加站点到公交线路中
addStation(line, 0, 1, "A");
addStation(line, 0, 2, "B");
addStation(line, 1, 0, "A");
addStation(line, 1, 3, "C");
addStation(line, 2, 0, "B");
addStation(line, 2, 4, "D");
addStation(line, 3, 1, "C");
addStation(line, 3, 4, "E");
addStation(line, 4, 2, "D");
addStation(line, 4, 3, "E");
int choice; //用户选择的功能
while (1) {
printf("欢迎使用公交线路管理系统,请选择功能:\n");
printf("1. 创建线路\n");
printf("2. 查询线路\n");
printf("3. 修改站点\n");
printf("4. 打印线路\n");
printf("5. 退出系统\n");
scanf("%d", &choice);
switch (choice) {
case 1:
//创建线路的功能
createLine(line);
break;
case 2:
//查询线路的功能
queryLine(line);
break;
case 3:
//修改站点的功能
modifyStation(line);
break;
case 4:
//打印线路的功能
printLine(line);
break;
case 5:
//退出系统的功能
printf("感谢使用,再见!\n");
return 0;
default:
//输入错误的处理
printf("输入错误,请重新选择。\n");
}
}
}
稍等
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_VERTEX_NUM 20
typedef struct {
int id;
char name[20];
} VertexType;
typedef struct ArcNode {
int adjvex;
struct ArcNode *next;
} ArcNode;
typedef struct {
VertexType vertices[MAX_VERTEX_NUM];
ArcNode *arcs[MAX_VERTEX_NUM];
int vexnum;
int arcnum;
} ALGraph;
void CreateALGraph(ALGraph *G) {
printf("请输入站点数量:");
scanf("%d", &G->vexnum);
printf("请输入站点信息:\n");
for (int i = 0; i < G->vexnum; i++) {
printf("请输入第%d个站点编号和名称:", i + 1);
scanf("%d %s", &G->vertices[i].id, G->vertices[i].name);
G->arcs[i] = NULL;
}
printf("请输入路线数量:");
scanf("%d", &G->arcnum);
printf("请输入路线信息:\n");
for (int i = 0; i < G->arcnum; i++) {
int from, to;
printf("请输入第%d条路线的起点和终点:", i + 1);
scanf("%d %d", &from, &to);
if (from < 0 || from >= G->vexnum || to < 0 || to >= G->vexnum) {
printf("站点编号超出范围,请重新输入!\n");
i--;
continue;
}
ArcNode *p = (ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = to;
p->next = G->arcs[from];
G->arcs[from] = p;
}
}
void DFS(ALGraph *G, int v, int visited[]) {
printf("%s ", G->vertices[v].name);
visited[v] = 1;
ArcNode *p = G->arcs[v];
while (p != NULL) {
if (visited[p->adjvex] == 0) {
DFS(G, p->adjvex, visited);
}
p = p->next;
}
}
void Query(ALGraph *G) {
int start;
printf("请输入起点编号:");
scanf("%d", &start);
if (start < 0 || start >= G->vexnum) {
printf("站点编号超出范围,请重新输入!\n");
Query(G);
return;
}
int visited[MAX_VERTEX_NUM] = {0};
printf("查询结果为:");
DFS(G, start, visited);
printf("\n");
}
void Modify(ALGraph *G) {
int id;
printf("请输入需要修改的站点编号:");
scanf("%d", &id);
for (int i = 0; i < G->vexnum; i++) {
if (G->vertices[i].id == id) {
printf("请输入修改后的站点名称:");
scanf("%s", G->vertices[i].name);
printf("修改成功!\n");
return;
}
}
printf("未找到该站点!\n");
}
int main() {
ALGraph G;
CreateALGraph(&G);
Query(&G);
Modify(&G);
return 0;
}
原题如下:
一个人有100元,打算买100只鸡。到菜市场一看,公鸡3元一只,母鸡5元一只, 小鸡1元三只,试求用100元买100只鸡各买多少只合适。
根据题目不难写出:
图的存储方式。图是由节点(也称为顶点)和边组成的数据结构,常见的图的存储方式包括邻接矩阵和邻接表。其中,邻接矩阵使用二维数组来表示图中的节点及其之间的连通关系,而邻接表则使用链表来表示每个节点以及所有与之相邻的边。邻接表比邻接矩阵更适合表示稀疏图或大规模图,因为它可以节省存储空间。
公交线路管理系统的设计。公交线路管理系统是一个基于图的应用,它需要存储站点和线路信息,并支持增加、修改、删除、查询等操作。在这个应用中,我们可以使用邻接表来存储图中的站点和边。对于每个站点,我们可以使用一个结构体来存储其名称以及指向相邻站点的边的指针。对于每个线路,我们可以使用一个链表来存储经过的站点,同时在邻接表中添加相应的边。
邻接表的实现。在邻接表的实现中,我们可以使用顶点数组和边链表来表示图。其中,顶点数组存储所有的站点,边链表则存储每个站点所连接的所有边。在具体实现中,我们可以使用一个 Vertex 结构体来表示每个顶点(即站点),其包含站点名称和第一条边的指针;使用一个 Edge 结构体来表示每个边,其包含指向目标节点的指针以及指向下一条边的指针。
站点信息的增加、修改和删除。对于站点信息的增加、修改和删除等操作,我们需要在邻接表中根据站点名称进行查找,并在必要的时候进行添加、修改或删除。其中,添加操作需要检查是否已经存在同名站点以及是否超过了最大站点数的限制;修改操作需要检查新名称是否与已有的站点名称重复;删除操作需要同时删除与该站点相邻的边。
线路查询。线路查询需要遍历从某个起始站点出发可以到达的所有站点,并输出其名称。常见的图遍历算法有深度优先遍历和广度优先遍历,其中深度优先遍历比较适合查询连通块或路径问题。在实现中,我们可以使用递归来进行深度优先遍历,并使用一个 visited 数组来记录已经访问过的站点。
c语言实现公交线路管理系统
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**************************函数声明************************************/
void init(); //初始化函数
void add(); //信息录入函数
void view(); //信息显示函数
void mod(); //信息修改函数
void modmeun(); //修改菜单
void modnavimeun(); //路线修改菜单
void del(); //信息删除函数
void find(); //信息查询函数
void findmeun(); //查询菜单
void findnavi(); //路线导航查询函数
void findnum(); //路线编号查询函数
void findstameun(); //站台信息查询菜单
void findsta(); //站台信息查询函数
void save(); //信息保存函数
void mainmeun(); //主菜单
char Test(char a,char b,char c); //菜单输入检测函数
/**************************宏定义声明************************************/
#define N 100 //公交车数量
/**************************结构体定义************************************/
struct station //途径站点信息
{
char c[20]; //站点名称
};
struct bus //公交车信息
{
char num[20]; //公交车路线编号
char name[20]; //司机姓名
int n; //站台数目
struct station b[12]; //站台名称
char topen[20]; //起始时间
char tclose[20]; //终止时间
int money; //票价
}a[N];
/**************************子函数定义************************************/
void init() //初始化函数
{
FILE *fp; //文件指针
int i;
if((fp=fopen("bus.txt","r+"))==NULL) //初次尝试打开"bus.txt"文本文件
{
printf("\n\t\t文件打开失败\n\n\t\t正在尝试创建新文件...\n");
fp=fopen("bus.txt","w"); //创建"bus.txt"文本文件
if((fp=fopen("bus.txt","r+"))==NULL) //再次判断是否打开成功
{
printf("\t\t文件创建失败!!!\n");
return;
}
}
fp=fopen("bus.txt","r+");
for(i=0;i<N;i++) //将磁盘中的信息输出到内存中
if(fread(&a[i],sizeof(struct bus),1,fp)!=1)
break;
fclose(fp);
printf("\n\t\t初始化完成!!!\n\n");
return;
}
void add() //信息录入函数
{
FILE *fp=NULL; //文件指针
int i,j;
char cc[20];
for(i=0;i<N;i++)
{
if(*a[i].num!='\0')
continue;
else
{
printf("\n添加第%d辆公交车路线记录:\n",i+1);
printf("\n请输入路线编码(3位编码,第一位为大写字母,后两位为数字):\n"); //路线编码
scanf("%s",cc);
for(j=0;j<N;j++) //检验是否重复
if(strcmp(a[j].num,cc)==0)
{
printf("\n与已有路线编码重复,按回车键返回!!!\n");
fflush(stdin); //清除键盘缓冲区
getchar();
system("cls");
return;
}
strcpy(a[i].num,cc);
printf("\n请输入司机姓名: "); //司机姓名
scanf("%s",a[i].name);
printf("\n请输入途经站台总数(>=2): "); //站台总数
scanf("%d",&a[i].n);
printf("\n");
if(a[i].n<2||a[i].n>12)
{
while(a[i].n<2||a[i].n>12)
{
printf("\n站台总数应满足(2<=n<=12),请重新输入: ");
scanf("%d",&a[i].n);
printf("\n");
}
}
for(j=0;j<a[i].n;j++)
{
printf("请输入第%d个站台名称: ",j+1); //站台名称
scanf("%s",a[i].b[j].c);
}
printf("\n自动生成公交路线:(1) %s",a[i].b[0].c);
for(j=1;j<a[i].n;j++)
{
printf(" ----> (%d) %s",j+1,a[i].b[j].c);
}
printf("\n\n请输入公交车的起始时间(格式为:时:分): "); //起始时间
scanf("%s",a[i].topen);
printf("请输入公交车的终止时间(格式为:时:分): "); //终止时间
scanf("%s",a[i].tclose);
printf("\n请输入公交车的票价: "); //票价
scanf("%d",&a[i].money);
printf("\n第%d辆公交车路线记录创建成功!!!\n",i+1);
save();
printf("\n\t按回车键返回!!!\n");
fflush(stdin); //清除键盘缓冲区
getchar();
system("cls");
return;
}
}
if(i==N)
printf("\n\n\n\t空间已满,不能录入!!!\n");
printf("\n\t按回车键返回!!!\n");
fflush(stdin); //清除键盘缓冲区
getchar();
system("cls");
return;
}
void view() //信息显示函数
{
int i,j,min;
struct bus t;
for(i=0;*a[i].num!='\0'&&i<N;i++) //按“路线编号”用选择法排序
{
min=i;
for(j=i+1;*a[j].num!='\0'&&j<N;j++)
if(strcmp(a[i].num,a[j].num)>0)
min=j;
t=a[i];
a[i]=a[min];
a[min]=t;
}
printf("\n\n 公交车信息库");
printf("\n********************************************************************************\n");
for(i=0;*a[i].num!='\0'&&i<N;i++)
{
printf("\t路线编号: %-6s\t单程票价: %d 元\t\t司机姓名: %s\n",a[i].num,a[i].money,a[i].name);
printf("\t起始时间: %-6s\t终止时间: %-6s\t站台总数: %d\n",a[i].topen,a[i].tclose,a[i].n);
printf("\t公交路线:(1) %s",a[i].b[0].c);
for(j=1;j<a[i].n;j++)
printf(" ---->(%d) %s",j+1,a[i].b[j].c);
printf("\n\n");
}
printf("\n********************************************************************************\n");
printf("\n\t\t公交车信息显示完毕!!!\n");
printf("\n\t\t输入回车键返回主菜单:");
fflush(stdin); //清除键盘缓冲区
getchar();
system("cls");
return;
}
void mod() //信息修改函数
{
int i,j,m=0;
char t,cc[20],mod[20];
printf("请输入要修改信息的公交车路线编号:\n");
scanf("%s",cc);
for(i=0;*a[i].num!='\0'&&i<N;i++) //查找所输入的公交车
{
if(strcmp(a[i].num,cc)==0)
{
m=1;
printf("\n\n\t\t已找到!!!\n");
while(1)
{
system("cls");
printf("\n\n 正在修改的公交车信息\n");
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
printf("\t路线编号: %-6s\t单程票价: %d 元\t\t司机姓名: %s\n",a[i].num,a[i].money,a[i].name);
printf("\t起始时间: %-6s\t终止时间: %-6s\t站台总数: %d\n",a[i].topen,a[i].tclose,a[i].n);
printf("\t公交路线:(1) %s",a[i].b[0].c);
for(j=1;j<a[i].n;j++)
printf(" ---->(%d) %s",j+1,a[i].b[j].c);
printf("\n\n");
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n\n");
modmeun();
fflush(stdin); //清除键盘缓冲区
t=Test(getchar(),'1','5'); //菜单检测输入函数
system("cls");
switch(t)
{
case '1': //修改路线编号
{
int k;
printf("\n请输入新的公交车编号:");
scanf("%s",mod);
for(k=0;*a[k].num!='\0'&&k<N;k++)
{
if(strcmp(a[k].num,mod)==0)
{
printf("与已有编号重复,按回车键返回主菜单\n");
fflush(stdin); //清除键盘缓冲区
getchar();
system("cls");
return;
}
}
strcpy(a[i].num,mod);
save();
break;
}
case '2': //修改车辆信息
{
printf("\n请输入新的司机姓名:");
scanf("%s",a[i].name);
printf("\n请输入新的公交车票价:");
scanf("%d",&a[i].money);
save();
break;
}
case '3': //修改行车路线
{
void modnavimeun(); //路线修改菜单
int k;
char z;
while(1)
{
system("cls");
modnavimeun();
fflush(stdin); //清除键盘缓冲区
z=Test(getchar(),'1','5'); //菜单检测输入函数
system("cls");
switch(z)
{
case '1': //添加站点
{
if(a[i].n+1>12) //判断是否满足条件
{
printf("\n站台总数达到12个,无法添加新站点\n\n按回车键返回\n");
fflush(stdin); //清除键盘缓冲区
getchar();
system("cls");
return;
}
printf("\n请输入需要添加第几个站点:");
scanf("%d",&k);
while(a[i].n+1<k)
{
printf("目前共%d个站点,无法添加第%d个站点\n请重新输入:",a[i].n,k);
scanf("%d",&k);
printf("\n");
}
a[i].n=a[i].n+1;
for(j=a[i].n;j>k-1;j--)
{
a[i].b[j]=a[i].b[j-1];
}
printf("\n请输入新添加的站点名称:");
scanf("%s",a[i].b[k-1].c);
save();
break;
}
case '2': //修改站点
{
printf("\n请输入需要修改第几个站点:");
scanf("%d",&k);
printf("\n请输入新的站点名称:");
scanf("%s",a[i].b[k-1].c);
save();
break;
}
case '3': //删除站点
{
printf("\n请输入需要删除第几个站点:");
scanf("%d",&k);
for(j=k-1;j<a[i].n;j++)
{
a[i].b[j]=a[i].b[j+1];
}
a[i].n=a[i].n-1;
save();
break;
}
case '4': //重置路线
{
printf("\n请输入新的途径站台总数(2<=n<=12): ");
scanf("%d",&a[i].n);
printf("\n");
while(a[i].n<2||a[i].n>12) //判断是否满足条件
{
printf("\n站台总数应满足(2<=n<=12),请重新输入: ");
scanf("%d",&a[i].n);
printf("\n");
}
for(j=0;j<a[i].n;j++)
{
printf("请输入新的第%d个站台名称: ",j+1);
scanf("%s",a[i].b[j].c);
}
printf("\t公交路线:(1) %s",a[i].b[0].c);
for(j=1;j<a[i].n;j++)
printf(" ---->(%d) %s",j+1,a[i].b[j].c);