校园导航系统(导航方式:步行,骑行,车行)

本文介绍了作者为满足学校课程设计要求,实现的校园导航系统,该系统采用邻接矩阵存储图结构,支持步行、骑行、车行三种导航方式。文章详细阐述了设计目的、内容要求,包括顶点、边结构和图结构体的构建,以及Dijkstra算法的实现。同时,还涵盖了文件读取、顶点和边的查找、最短路径展示等功能的实现过程。

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

前言

学校数据结构课程要求做的课程设计

一.设计目的

     (1).首先,在选择校园导航系统的图的存储结构时,由于当时还没有确定课题题目,最后一段时光临时学习了图的两种存储结构,由于本人认为邻接矩阵存储比较简单,就选择了该存储结构。

       (2).其次,该课程设计是本人第一次进行的比较认真的设计,即使比较简单,但也经历了一个星期左右的设计加调试,在不断选择中所得到的成果,即使最后可能在学校所得到的分数不是很高,但我觉得有一定的纪念意义,索性就发布出来,希望能对大家有一定的帮助。

        (3).最后,该系统实现了网上我一直找不到的导航方式的一定功能,并从文件中读取数据,结合网上其他人的方法,给出了我自身对于导航方式的理解。

二.设计内容与要求

        一.设计要求

 为本校设计一个校园导航程序,具体要求如下:

① 校园地图存储于格式自定义的文本文件中,包括地点编号、名称、简介;道路名称、 长度、 种类(车行、骑行、步行)等信息,至少包含 15 个地点、25 条道路。

② 所存储的校园地图需以图形方式输出。

③ 能根据编号(或名称)查询任意地点、道路的相关信息。

④ 能根据指定的出发、目的地点、导航方式(车行、骑行、步行),计算出最短路径。

⑤ 能为用户提供从指定地点出发游览完其他所有地点的路线信息。 涉及算法及知识:图的创建、遍历、最短路径、文本文件读 API。

        二.设计内容

        首先,构建校园导航图的各个组成结构:

一:顶点结构

typedef struct Vex //景点信息
{
    int position; //编号
    char name[Max];//名称
    char introduction[100];//介绍
}VexInfo[100];

其中,position是指各个顶点的编号,name指的是顶点名称,introduction是指顶点介绍

二:边结构

typedef struct Rd {
    char name[Max];
    char infor[40];
    int length;
    int type;   // 1-车行道,2-骑行道,3-步行道
    int last;				//道路一端的序号
    int next;				//道路另一端的序号
}Road[100];

该边结构中包含一条边的上一个顶点和下一个顶点,边的名字和介绍,边的长度,最后是边的类型

三:邻接矩阵

typedef struct ArcNode
{
    int adj;
}AdjMAtrix;

其实,可以省略该结构体,直接在图结构体中定义邻接矩阵,此处本人不改了

四:图结构体

typedef struct maps //景点的图
{
    int VexNum; //顶点数
    int ArcNum; //边数
    VexInfo ves;//顶点表
    Road rd;//边表
    AdjMAtrix arcs[Max][Max];//邻接矩阵

}Map;

其中,图的成员包含了顶点数和边数,也包含了顶点信息和边的信息,最后包含一个邻接矩阵

---------------------------------------------------------------------------------------------------------------------------------

三.设计过程

 

文件路径在我的电脑中为D盘下

fopen和fscanf为文件的两个基本操作,注意在读取文件时要将文本文件的格式转换成ANSI,否则读出来的汉字为乱码,此处重点注意!!!!!!

文件读取操作并不难,直接上网现查就ok,基本都是这么个模式

---------------------------------------------------------------------------------------------------------------------------------

一(定位顶点表下标函数)

        基本操作,注意,为使序号与下标一一对应,不管是上方的文件读取中的循环,还是往后的循环,都从下标1开始进行,直到等于顶点数或边数结束

int LocateVex(Map& G, int v) {
    //i因为是需要记录使用的变量,因此定义在外部
    int i;
    //遍历图的一维顶点数组,找到顶点v的下标
    for (i = 1; i <= G.VexNum; i++) {
        if (G.ves[i].position == v) {
            //如果已经找到直接退出循环,不需要再次进入循环
            break;
        }
    }
    //如果找不到,输出提示语句,返回-1
    if (i > G.VexNum) {
        printf("No such vertex.\n");
        return -1;
    }
    //寻找成功返回v的下标
    return i;
}

二(无向图创建函数)

参数为Map类型的指针G

(1)在该函数中定义边数和顶点数

(2)并定义了两个图外部的表,在使用read_graph()函数后,顶点表和边表中从文件中读取到了数据

(3)之后两个for循环的操作就是用外部的顶点表和边表为图中的顶点表和边表填充数据

(4)再然后,就是初始化邻接矩阵,并使用最后的双重for循环为邻接矩阵赋边值(即权值)

void CreateUDG(Map* G) {
    //设置图的顶点数与边数
    int i, j, k;
    int v1, v2;
    G->VexNum = 20;
    G->ArcNum = 31;
    Rd road[Max];
    Vex ves[Max];
    read_graph(ves, road);
    for (i = 1; i <= G->VexNum; i++) {
        G->ves[i].position = ves[i].position;
        strcpy(G->ves[i].name, ves[i].name);
        strcpy(G->ves[i].introduction, ves[i].introduction);

    }
    for (int n = 1; n <= G->ArcNum; n++)
    {
        strcpy(G->rd[n].name, road[n].name);
        strcpy(G->rd[n].infor, road[n].infor);
        G->rd[n].last = road[n].last;
        G->rd[n].next = road[n].next;
        G->rd[n].type = road[n].type;

    }
    //初始化
    for (i = 1; i <= G->VexNum; i++)
    {
        for (j = 1; j <= G->VexNum; j++)
 
实现简单的查询,各风景的查询,调用各函数,实现课程设计的目标。其中包含三个功能,一个是直接进入导航系统,利用主函数中已有的数据,进行查询:一个是进行创建数据,本程序中初始数据为农大的导航数据,如果需要也可以自己建立一个;最后一个是退出功能。设计该函数的目的是为了能够多次得应用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、付费专栏及课程。

余额充值