C/C++校园导航图的实现

该博客介绍了使用C/C++设计一个包含30个以上节点的校园导航图,每个节点代表校园景点,包含名称、代号和简介。通过迪杰斯特拉算法实现任意两点间的最短路径查询,同时具备实时路径调整功能。提供了代码实现、设计思路及界面截图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C/C++校园导航图的实现

课程设计题目2——校园导航图的实现
一、设计内容
(1)设计一个学校的校园平面图,所选结点不少于30个。以图中顶点表示校园各景点,存放景点名称、代号、简介等信息:以边表示路径,存放路径长度等相关信息。
(2)为来往客人提供图中任意景点相关信息的查询。
(3)为来往客人提供图中任意景点的问路查询,即任意2个景点间的最短路径,给出具体路径和路径长度。
二、设计要求
(1)除了完成基本功能外,最好能提供实时路径查询,例如某条路径的临时关闭(需在程序中实现)后的最短路径的计算。
(2)提交设计报告,报告包括代码、设计思路〔流程图)和实现界面截图等。

设计思想

程序需要先构建邻接矩阵,将读入的顶点和边的信息存入邻接矩阵(Adjacency Matrices),然后通过迪杰斯特拉(Dijkstra)算法求两点之间的最短路径。

部分代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

/*顶点属性*/
typedef struct _tVertex {
	char name[256];		/*属性名称*/
	char description[1024];	/*属性描述*/
} Vertex, * pVertex;

/*顶点列表*/
typedef struct _tVertexList {
	int len;		/*表长度*/
	pVertex data;	/*表元素*/
} VertexList, * pVertexList;

/*权值*/
typedef unsigned int WEIGHT, * pWEIGHT;

/*邻接矩阵*/
typedef struct _tAdjacentMatrix {
	int size;		/*矩阵顶点个数*/
	WEIGHT* data;	/*矩阵权值元素*/
} AdjacentMatrix, * pAdjacentMatrix;

/*图结构*/
typedef struct _tGraph {
	VertexList vertexes;	/*顶点描述信息*/
	AdjacentMatrix adjmatrix;	/*顶点连接关系*/
} Graph, * pGraph;

enum {
	VISIT_STATE_VOID,	/*未标记*/
	VISIT_STATE_MARK	/*已标记*/
};

/*顶点被访问标识*/
typedef unsigned char VISIT, * pVISIT;

/*Dijkstra算法需要用到的数据结构*/
typedef struct _tDijkstra {
	int len;
	pVISIT vis;
	pWEIGHT dis;
	int* pre;
} Dijkstra, * pDijkstra;

#define INFINITELY_GREAT ~0U /*无穷大*/

/*创建顶点列表*/
void generateVertexList(pVertexList list, int vertexes) {
	list->len = vertexes;
	list->data = (pVertex)malloc(sizeof(Vertex) * list->len);
	memset(list->data, 0U, sizeof(Vertex) * list->len);
}

/*创建邻接矩阵*/
void generateAdjacentMatrix(pAdjacentMatrix adjmatrix, int vertexes) {
	adjmatrix->size = vertexes;
	adjmatrix->data = (pWEIGHT)malloc(sizeof(WEIGHT) * (vertexes * vertexes));
	memset(adjmatrix->data, INFINITELY_GREAT, sizeof(WEIGHT) * (vertexes * vertexes));
}

/*销毁顶点列表*/
void freeVertexList(pVertexList list) {
	if (list) {
		if (list->data) {
			free(list->data);
			list->data = NULL;
		}
	}
}

/*销毁邻接矩阵*/
void freeAdjacentMatrix(pAdjacentMatrix adjmatrix) {
	if (adjmatrix) {
		if (adjmatrix->data) {
			free(adjmatrix->data);
			adjmatrix->data = NULL;
		}
	}
}

/*创建图*/
pGraph generateGraph(int vertexes) {
	pGraph graph = (pGraph)malloc(sizeof(Graph));
	memset(graph, 0U, sizeof(Graph));
	generateVertexList(&graph->vertexes, vertexes);
	generateAdjacentMatrix(&graph->adjmatrix, vertexes);
	return graph;
}

/*销毁图*/
void freeGraph(pGraph graph) {
	if (graph) {
		freeVertexList(&graph->vertexes);
		freeAdjacentMatrix(&graph->adjmatrix);
		free(graph);
	}
}

/*设置顶点名称*/
void setVertexName(pGraph graph, int index, const char* name, const char* summary) {
	strcpy(graph->vertexes.data[index].name, name);
	strcpy(graph->vertexes.data[index].description, summary);
}

/*获取顶点名称*/
const char* getVertexName(pGraph graph, int index) {
	return graph->vertexes.data[index].name;
}

/*查找顶点索引*/
int findVertexIndex(pGraph graph, const char* name) {
	int index = 0;
	while (index < graph->vertexes.len) {
		if (strcmp(graph->vertexes.data[index].name, name) == 0) {
			return index;
		}
		++index;
	}
	return -1;
}

/*设置两相邻顶点的边的权值*/
void setEdgeWeight(pGraph graph, int from, int to, WEIGHT weight) {
	graph->adjmatrix.data[(graph->adjmatrix.size * from) + to] = weight;
}

/*得到两相邻顶点的边的权值*/
WEIGHT getEdgeWeight(pGraph graph, int from, int to) {
	return graph->adjmatrix.data[(graph->adjmatrix.size * from) + to];
}

测试数据

17 46
图书馆 这是学校的图书馆。
综合楼 这是学校的综合楼。
实验楼 这是学校的实验楼。
餐厅 这是学校的餐厅。
南门 这是学校的南门。
东门 这是学校的东门。
西门 这是学校的西门。
北门 这是学校的北门。
操场 这是学校的操场。
家属楼 这是学校的家属楼。
中心湖 这是学校的中心湖。
正门 这是学校的正门。
南区食堂 这是学校的南区食堂。
北区食堂 这是学校的北区食堂。
东区食堂 这是学校的东区食堂。
西区食堂 这是学校的西区食堂。
生物楼 这是学校的生物楼。
图书馆 综合楼 123
综合楼 图书馆 123
图书馆 餐厅 256
餐厅 图书馆 256
综合楼 实验楼 243
实验楼 综合楼 243
综合楼 餐厅 242
餐厅 综合楼 242
餐厅 实验楼 279
实验楼 餐厅 279
餐厅 南门 369
南门 餐厅 369
实验楼 南门 372
南门 实验楼 372
南门 操场 466
操场 南门 466
操场 东门 308
东门 操场 308
操场 正门 188
正门 操场 188
正门 西门 375
西门 正门 375
正门 南区食堂 115
南区食堂 正门 115
操场 南区食堂 261
南区食堂 操场 261
操场 中心湖 294
中心湖 操场 294
东门 西门 137
西门 东门 137
西门 北门 269
北门 西门 269
西门 家属楼 236
家属楼 西门 236
南区食堂 中心湖 278
中心湖 南区食堂 278
南区食堂 北区食堂 149
北区食堂 南区食堂 149
北区食堂 东区食堂 144
东区食堂 北区食堂 144
中心湖 南区食堂 565
南区食堂 中心湖 565
西区食堂 生物楼 104
生物楼 西区食堂 104
东区食堂 生物楼 376
生物楼 东区食堂 376

运行效果

程序截屏1.png

程序截屏2.png

源码联系UP主 -> https://space.bilibili.com/329101171

实现简单的查询,各风景的查询,调用各函数,实现课程设计的目标。其中包含三个功能,一个是直接进入导航系统,利用主函数中已有的数据,进行查询:一个是进行创建数据,本程序中初始数据为农大的导航数据,如果需要也可以自己建立一个;最后一个是退出功能。设计该函数的目的是为了能够多次得应用dijkstra函数进行查询最短路径。同时该函数可以列出各景点的代号和对应的名称,这样大家只要输入代号就行了。方便进行查询。下面分别描述这些函数,建立它们函数原型。 1、主函数 函数原型:void main(void) 功 能:控制程序。 参 数:void 返 回 值:void 要 求:管理菜单命令并完成初始化。 2、菜单选择和处理函数 函数原型:int menu() 功 能:处理选择的菜单命令并接收用户选择的命令代码。 参 数:int 返 回 值:int 工作方式:返回命令代码的整数值,根据命令,调用相应函数。 要 求:只允许选择规定键,如果输入不合要求,则提醒用户重新输入。 3、建立邻接矩阵函数 函数原型:void createadj() 功 能:重新建立一个学生信息的记录。 参 数:void 返 回 值:void 工作方式:在需要的时候就可以有主菜单中调用 void createadj()函数。 要 求:必需输入信息记录,然后才能调用出search()函数进行查询。 4、dijkstra函数 函数原型:void dijkstra(intx,inty) 功 能:求两点间的最短路径 参 数:void 返 回 值:void 工作方式: 该函数被其它一些函数调用。 5、结束程序 函数原型:int Exit() 功 能:使程序正常结束运行 参 数:int 返 回 值:1 工作方式:在操作都完成后,可以调用int Exit()函数,使函数最终返回 1 运行exit(1),程序正常结束。 要 求:运行Exit()函数后可以选择是否要保存,选择y则先保存再返 回1值;如果选择n直接返回1值。详细的程序设计应从下到上,在本设计中就要先设计createadj函数;然后设计dijkstra函数;接着是search函数;menu函数;最后才是main函数。如此设计能大大提升设计速度,因为从下往上使编程时的高试过程简单许多,而做课程设计花费时间最多的就是调试过程。对于各函数的详细设计,各函数的N—S图如下: (1)Createadj函数 (2)Dijkstra函数          (3)Search函数          (4)Menu函数          (5)main函数          2.4 程序编码   把详细设计的结果进一步求精为程序设计语言程序。同时加入一些注解和断言,使程序中逻辑概念清楚;编写过程中参考各种的教材和材料,使程序编写的正确性大有提高,同时也许到许多实践知识,增加了实践经验。 2.5 程序调试与测试    程序编写总是出现各种各样的错误,但是难点不是修改错误,而是找出错误。在大量的源程序中找出错误难度很大,但有了一定的方法,就能节省大量的时间,在这次课程设计中我运用的调试方法主要有2种:     一是借助调试工具。利用Turbo C中提供的程序专门调试工具Debugger程序,可以很容易找出程序中的各种语法错误。但是遇到一些逻辑错误时却又无从着手。这时我就用下面一种方法。     二是在程序中插入打印语句。猜测出大致的错误位置,选则一些主要变量,在关键部位插入打印语句,打印出这个主要变量,看其是否与理论上的一样,在多个位置插入,如果有个位置的值与理论值一样,另一个位置与理论值不一样,则错误就落在这两个位置之间,然后再多测试几个位置缩小范围,直到找出错误。  例如;我在调试main()主函数时,程序能够运行,三个选项都能选择,创建函数能够正常运行,也能正常退出,但在选第一条进入校园导航后,打印出来的列表却是空的,源程序中的初始化数据没有显示出来,我又尝试输入两个结点进行查找,发现没有输出路线,所以我猜测初始化数据没有被正常写入。但不知道为何没有被正常写入,首先怀疑是初始化时附值发生错误,查阅各种资料进行校验,发现没有错误。后来经过综合分析,发现最有可能是n值在search()函数中发生错误,于是我在search()函数中插入打印n 的语句,运行后发现输出的n为0,初始化数据中有11个结点,n应该为11,所以n 在这个地方发生错误,我又在main()主函数中打印出n 的值,n=11,是正确的。所以错误就在search()函数中,也就说是当运行case1,运行到search()函数时,n从11变为0,针对这个错误,我把变量n改为宏定义,因为n 是代表结点个数,不管在哪个函数中它的值都是一样的才对。改完后运行程序,成功! 本设计文件的注释如上,已给出详细的说明,下面仅以文件为单位说明各个函数的作用和特点,在必要的地方给予一定说明。  3.1、guide.h文件 使用条件编译。以下是头文件中语句 /********************************************* *头文件(.h) ********************************************/ #include "stdio.h" #include "conio.h" #include "alloc.h" #define n0 100 #define infi 32767 /*“无穷大*/ int adjmatrix[n0+1][n0+1];     /*邻接矩阵*/ int n=11; struct node             /*表结点*/ { char name[20];       /*下一个表结点与它们之间的距离*/ }place[12]={{"ShiDiGongYuan"},   /*表结点初始化,即写各景点名称*/    {"CangRongGongYu"},    {"YinHuiLou"},    {"TuoHuanGuanChang"},    {"DiBaShiTang"},    {"XiaoYiYuan"},    {"TuShuGuan"},    {"TiYuGuan"},    {"ZhongHuaGuanChang"},    {"ChuangXinLou"},    {"YiFuTuShuGuan"},    {"BoXueLou"}};  void createadj()          /*建立邻接表*/  void dijkstra( int x,int y)     /*dijkstra求最小生树*/  void search()            /*搜索最短路径*/  menu()               /*菜单函数*/          /********************************************* *建立邻接表 ********************************************/ void createadj()  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值