一、实验内容及实验要求

【问题描述】

设计一个校园导游程序,为来访的客人提供各种信息查询服务。

【基本要求】

  1. 设计你所在学校的校园平面图,所含景点不少于10个.以图中顶点表示校 内各景点,存放景点名称、代号、简介 等信息;以边表示路径,存放路径长度等相关信息。
  2. 为来访客人提供图中任意景点相关信息的查询。
  3. 为来访客人提供图中任意景点的问路查询,即查询任意两个景点之间的一条最短的简单路径。

【测试数据】

以江苏科技大学长山校区为例。

【实现提示】

一般情况下,校园的道路是双向通行的,可设校园平面图是一个无向网,顶点和边均含有相关信息.


二、问题分析

概述

  • 本实验的编程语言采用Java,并用Swing实现了GUI。用户可以点击校内景点的图片来查询该景点的详细信息,程序支持查询任意两景点间的最短路径,并可以根据初始点的位置提供推荐游览路径。
  • 数据结构采用了图的邻接矩阵存储,并且为了更加方便的实现Floyd算法,还提供了图的前趋结点数组。
  • 最短路径的查询采用了Floyd算法
  • 推荐游览路径即是从一个指定景点开始,不重复的游览完所有景点的路径,这一路径的计算采用了马踏棋盘算法,本质上采用了DFS图的深度优先遍历,另外还采用了贪心思想进行了优化。

最短路径——Floyd算法

Floyd算法可以给出网络中任意两个结点之间的最短路径,因此它是比Dijkstra更一般的算法。Floyd算法的思想是将n个结点的网络表示为n行n列的矩阵,而矩阵中的元素Di,j表示从结点i到结点j的距离,如果两点直接没有边相连,则相应的元素就是无穷∞。
具体过程描述如下:

a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。   
b.对于每一对结点 i 和 j,看看是否存在一个结点 k 使得从 i 到 k 再到 j 比己知的路径更短。如果是更新它,直到所有的结点都已经尝试过。

伪代码描述如下:

枚举顶点k ∈ [1,n]以顶点k为中介点,枚举所有顶点对i和j(i ∈ [1,n],j ∈1[1,n])如果dis[i][k] + dis[k][j] <dis[i][j]成立赋值dis[i][j] = dis[i][k] + dis[k][j]

注意Floyd算法为了能回溯得到最短路径的结果,需要声明一个前趋结点数组,用来保存所有点的前一个结点,每次找到更短的路径时,需要更新这一数组。

推荐游览路径——马踏棋盘算法

推荐游览路径是从一个指定景点开始,不重复的游览完所有景点的路径,即在图中寻找一条由指定结点开始的哈密尔顿路径。这一问题可以通过类似马踏棋盘问题的算法来解决,实质上是采用了图的深度优先遍历和贪心算法的优化。
该算法具体过程描述如下:

图的数据结构与前一个算法相同,采用的还是邻接矩阵。
先将当前位置结点设置为已访问,然后根据当前的结点位置,计算下一步还能走哪些位置,并把这些位置放入到一个集合ArrayList中,每走一步,step+1。
遍历ArrayList中存放的所有位置,看看哪个可以走通,如果走通就继续,走不通就回溯。
最后判断是否完成了任务:使用step和应该走的步数比较,如果没有达到数量,则表示没有完成任务,将整个结果置0。

注意这样的搜索结果会根据策略的不同而改变,不同的策略执行的时间快慢也不一样,在这里,我们可以通过贪心算法对它进行优化,具体过程如下

在马踏棋盘算法获取下一步可以走的位置集合ArrayList之前,我们需要对ArrayList集合中点的下一步的所有集合的数目进行非递减排序
这样在ArrayList中第一个结点就是下一步应该走的结点,我们需要优先选择它,因为它的后续结点最少,代表着需要回溯的点也越少。

采用了贪心算法优化之后,程序执行的时间效率会大大提高。


三、逻辑设计

程序有三个包分别为:domain、service、 ui
domain包下提供了两个类:

  • View类是景点的抽象,生成的对象代表学校里的景点,具有私有属性:景点的编号、名称以及景点的介绍。
  • MGraph类是图的数据结构,采用邻接矩阵表示,顶点数组中存放每一个景点的对象,该类的构造方法初始化了图的结点和边。

Service包下提供了三个类:

  • ShortestPathService类提供了求图中任意两个景点之间的最短路径的Floyd算法。
  • TourPathService类提供了求推荐游览路径的马踏棋盘算法。
  • ViewsService类用来展示各景点的详细信息。

ui包中是Swing的一些组件类,用于实现GUI,同时其中的MainInterface类也是程序的入口。

以下是程序的流程图:


四、物理设计

本实验的数据结构采用图的邻接矩阵各算法也依据邻接矩阵来实现。图中每个结点都是一个景点View类的对象。
下图是景点的带权无向图:

以下是图以及景点类的数据结构:

package com.domain;import java.util.Arrays;/*类MGraph:用于表示学校景点的无向网
*/
public class MGraph {//最大顶点数public static final int MAX_SIZE = 20;//最大权值,即∞public static final int MAX_INT = 65535;//顶点数组private View[] vertex = new View[MAX_SIZE];//图的邻接矩阵private int[][] adj = new int[MAX_SIZE][MAX_SIZE];//图的前趋结点数组private int[][] pre = new int[MAX_SIZE][MAX_SIZE];//图的顶点数和边数private int vertexNum, edgeNum;//初始化图结构public MGraph() {//设置结点数与边数vertexNum = 12;edgeNum = 17;//初始化顶点数组initialVertex(vertex);//初始化邻接矩阵initialAdj(adj);//初始化前趋结点数组initializePre(pre);}//初始化顶点数组private void initialVertex(View[] vertex) {vertex[0] = new View(1, "行政楼", "办公主楼,校领导办公的地方~");vertex[1] = new View(2, "海韵湖", "海韵湖连通着长江,景色优美,是饭后散步的好地方,外围有红蓝塑胶跑道,学校时常举办环湖跑比赛");vertex[2] = new View(3, "图书馆", "图书馆总共五层,室内环境优雅,藏书众多,更有窗边观湖雅座,是各大卷王的必争之地");vertex[3] = new View(4, "东食堂", "东食堂有很多特色菜肴,食堂对面就是图书馆");vertex[4] = new View(5, "东操场", "体育锻炼的好地方,时常举办足球比赛");vertex[5] = new View(6, "南门", "校门庄严气派,毗邻长晖路,马路对面有烧烤和麻辣烫卖");vertex[6] = new View(7, "文体中心", "一楼有乒乓球馆、健美操馆、健身房,二楼有室内篮球场和羽毛球场,是锻炼身体的好去处,旁边还有船苑剧场可以看电影");vertex[7] = new View(8, "西操场", "平时举办运动会的地方");vertex[8] = new View(9, "经世楼", "学校四座教学楼中的一座,其它几个分别为笃学楼、明德楼以及文理大楼,教师多媒体讲台、多功能显示屏、打印机、自动贩卖机等基础设施完善");vertex[9] = new View(10, "文理大楼", "长山校区的地标建筑,共21层,到天台可以俯瞰整个校园景色,气势磅礴");vertex[10] = new View(11, "西食堂", "西食堂有三层,第三层是民族食堂,可以品尝各地的特色菜肴");vertex[11] = new View(12, "西宿舍区", "西片区学生住宿的地方,分为7个组团,从宿舍到教学楼要跑好多路QAQ");}//初始化邻接矩阵private void initialAdj(int[][] adj){//先初始化for (int i = 0; i<vertexNum;i++){for (int j = 0; j<vertexNum;j++){adj[i][j] = MAX_INT;}adj[i][i] = 0;}adj[0][1]=300;      //行政楼-海韵湖adj[1][0]=300;adj[0][9]=700;      //行政楼-文理大楼adj[9][0]=700;adj[9][8]=100;      //文理大楼-经世楼adj[8][9]=100;adj[2][9]=400;      //文理大楼-图书馆adj[9][2]=400;adj[1][2]=600;      //海韵湖-图书馆adj[2][1]=600;adj[7][8]=100;      //西操场-经世楼adj[8][7]=100;adj[2][7]=550;      //西操场-图书馆adj[7][2]=550;adj[7][10]=250;     //西食堂-西操场adj[10][7]=250;adj[6][7]=100;      //文体中心-西操场adj[7][6]=100;adj[2][3]=100;      //图书馆-东食堂adj[3][2]=100;adj[6][10]=300;     //西食堂-文体中心adj[10][6]=300;adj[3][6]=550;      //文体中心-东食堂adj[6][3]=550;adj[10][11]=200;        //西宿舍区-西食堂adj[11][10]=200;adj[5][6]=250;      //文体中心-南门adj[6][5]=250;adj[3][4]=100;      //东食堂-东操场adj[4][3]=100;adj[5][11]=700;     //西宿舍区-南门adj[11][5]=700;adj[4][5]=250;      //南门-东操场adj[5][4]=250;}//初始化前趋结点数组private void initializePre(int[][] pre){for (int i = 0; i<vertexNum;i++){Arrays.fill(pre[i],i);}}public View[] getVertex() {return vertex;}public void setVertex(View[] vertex) {this.vertex = vertex;}public int[][] getAdj() {return adj;}public void setAdj(int[][] adj) {this.adj = adj;}public int getVertexNum() {return vertexNum;}public void setVertexNum(int vertexNum) {this.vertexNum = vertexNum;}public int getEdgeNum() {return edgeNum;}public void setEdgeNum(int edgeNum) {this.edgeNum = edgeNum;}public int[][] getPre() {return pre;}public void setPre(int[][] pre) {this.pre = pre;}
}
package com.domain;
/*类View:用于表示每一个景点
*/
public class View {//景点的编号private int id;//景点的名称private String name;//景点的介绍private String introduction;public View(int id, String name, String introduction) {this.id = id;this.name = name;this.introduction = introduction;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getIntroduction() {return introduction;}public void setIntroduction(String introduction) {this.introduction = introduction;}
}

下面是最短路径Floyd算法的代码:

//Floyd算法private void floyd() {//变量保存距离int len = 0;//对中间结点遍历,k就是中间结点的下标for (int k = 0; k < mGraph.getVertexNum(); k++) {//从i结点开始出发for (int i = 0; i < mGraph.getVertexNum(); i++) {//到达j结点for (int j = 0; j < mGraph.getVertexNum(); j++) {//从i结点出发,经过中间结点k,到达j结点的距离len = dis[i][k] + dis[k][j];//如果比原来的距离小,更新距离和前趋结点if (len < dis[i][j]) {dis[i][j] = len;pre[i][j] = pre[k][j];}}}}}

下面是推荐游览路径马踏棋盘算法及其使用贪心算法优化的代码:

 /*DFS寻找哈密尔顿路径:马踏棋盘算法result为图,id为当前点(从0开始),step为步数记录,初始步数为1*/private void traversalMap(int[] result, int id, int step){//更新结果图result[id] = step;//标志该位置已经访问visited[id] = true;//获取当前位置可以走的下一个位置的集合ArrayList<Integer> ps = next(id);//利用贪心算法排序优化,优先选择下一步可选择位置最少的点sort(ps);//遍历ps,递归回溯while (!ps.isEmpty()){//取出下一个可以走的位置Integer p = ps.remove(0);//判断该点是否被访问过if (!visited[p]){//如果没有访问过,进行下一步traversalMap(result,p,step+1);}}//判读是否遍历了所有的点,使用step和应该走的步数比较,如果没有到达数量,将整个结果置0//step<结点数 成立的情况有两种//1.所有结点到目前为止仍然没有走完//2.所有结点到目前为止已经走完,处于回溯过程(无路可走)if (step<mGraph.getVertexNum() && !finished){result[id] = 0;visited[id] = false;}else {//如果完成了finished = true;}}//根据当前点的位置,计算还能走哪些位置,把这些点的id放入一个ArrayList中,id从0-11private ArrayList<Integer> next(int id) {ArrayList<Integer> ps = new ArrayList<>();for (int j = 0; j<mGraph.getVertexNum(); j++) {//如果这条路连通,就把点加入if (dis[id][j]<MGraph.MAX_INT){ps.add(j);}}return ps;}//利用贪心算法对DFS优化//根据当前这一步的下一步的选择位置,进行非递减排序,减少在DFS时的回溯次数private void sort(ArrayList<Integer> ps){ps.sort(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return next(o1).size()-next(o2).size();}});}

查询景点详细信息的代码最为简单,但用GUI实现景点的展示对我这个新手来说还是很繁琐的。

//传入景点id,返回景点的介绍(字符串)public String getViewInformation(int id){return vertex[id-1].getIntroduction();}

总结

对于本次实验来说还有许多可以改进的地方

  1. 图的结点是不可以修改的,其实一开始也考虑过通过文件读取图中结点以及边的权值信息,或者用户可以手动修改结点和边的信息。但因为想要用GUI展示,对于结点的修改肯定要动态的改变地图样貌,这样一来实现起来就非常困难,而且用户对结点修改的步骤也较为繁琐,所以索性就把结点和边定死了。
  2. 图不能动态的展示,每次查询最短路径只能通过文字信息展现,不能在地图上画出此次查询的最短路线。因为要实现这一功能需要加上窗口的坐标变换和计算,画出相应的行动轨迹,对我来说过于困难。
  3. 功能较少,只有查询景点、最短路径和推荐路径这三个功能。其实一方面可以根据路况信息、甚至是地形的坡度来动态的改变边的权值。另一方面可以增加每个景点的推荐程度这一信息来对景点进行排序,给用户优先级的推荐等。
  4. 推荐路径只能推荐从当前结点出发一个可行的哈密尔顿道路,并不能求出游览所有景点一次的最短道路。

数据结构课程设计——项目2:校园导游咨询相关推荐

  1. 数据结构课程设计项目2:校园导游咨询-预习报告

    目录 一.题目 二.需求分析 三.设计思路及重难点 四.编程语言 一.题目 项目2:校园导游咨询 [问题描述] 设计一个校园导游程序,为来访的客人提供各种信息查询服务. [基本要求] (1) 设计你所 ...

  2. 数据结构课程设计——项目2:校园导游咨询(图 Dijkstra算法寻找最短路径)

    数据结构课程设计--项目2:校园导游咨询(图 Dijkstra算法寻找最短路径) 一.问题描述和项目要求 1.1 问题描述 1.2 基本要求 二.问题分析 2.1 程序功能设计分析 2.2 程序实现分 ...

  3. 数据结构课程设计——项目1:中国计算机设计大赛赛事统计

    1.问题描述 参加计算机设计大赛的n个学校编号为1~n,赛事分成m个项目,项目的编号为1~m.比赛获奖按照得分降序,取前三名,写一个统计程序产生各种成绩单和得分报表. 2.基本要求 1)每个比赛项目至 ...

  4. 校园导游系统数据结构课程设计(附完整代码)

    1 问题内容与目的要求 1.1 算法产生的背景: Floyd 算法又称为加点法.插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法.该算法名称以创始人之一.1978 年图灵奖获 ...

  5. java校院导游程序课程设计_数据结构课程设计之校园导游系统

    数据结构课程设计之校园导游系统 放假到现在终于安下心来要搞点学习了,现在对放假前一周的数据结构课设做一个总结,快放假的时候搞数据结构课设,当时满脑子都是期末考试忙着复习,根本没啥心思去做.所以课设一共 ...

  6. 数据结构课程设计 校园导游系统 c++

    元旦前后利用几天时间完成了数据结构课程设计,学期初计划搞一个*精美* 些的课程设计,最后还是一拖再拖,到最后只来得及实现些基本功能. 团队协作完成,所以代码风格不尽相同. 另外才疏学浅,若有错误恳请不 ...

  7. 基于C语言的数据结构课程设计(学生管理系统、停车场管理、家谱管理、校园导航系统)

    一.设计目的 本课程设计是软件工程学生的必修课程,数据结构与算法课程设计既是一门基础课程,又是一门实践性课程.通过本实训课程的学习和训练,使同学学会分析研究数据对象的特性,学会数据的组织方法,以便选择 ...

  8. 广工数据结构课设——校园导游咨询(C语言)

    效果图 [运行环境] Windows系统 [问题描述] 设计一个校园导游程序,为来访的客人提供各种信息查询服务. [基本要求] (1)设计你的学校的校园平面图,所含景点不少于10个.以图中顶点表示校内 ...

  9. 数据结构课程设计之项目三---算术表达式求解

    目录 问题描述 基本要求 问题分析 逻辑设计 物理设计 存储结构 其他模块功能核心函数伪代码 总结 问题描述 设计一个简单的算术表达式计算器. 基本要求 实现标准非负整数类型的四则运算中缀表达式的求值 ...

最新文章

  1. RSA签名算法,计算调用加密报文,安全传输
  2. mongodb 安装时错误
  3. 关于阿里面试的的一个小题
  4. dns的主从服务器的简单配置
  5. 英语影视台词---八、the shawshank redemption
  6. randn函数加噪声_语义分割中常用的损失函数1(基础篇)
  7. python的os库的remove可以删除只带有只读属性的_扩展库os中的方法remove()可以删除带有只读属性的文件。(2.0分)_学小易找答案...
  8. 反向传播与梯度消失梯度爆炸
  9. C# winform 弹出输入框
  10. GitHub GraphQL API已正式可用
  11. 基于Hadoop生态系统的一种高性能数据存储格式CarbonData(基础篇)
  12. 最好用的五大服装进销存管理软件,强推第一个
  13. 电厂计算机室建议,火力发电厂计算机室、控制室、电子设备间,应设排烟设施,机械排烟系统的排烟量可按房间换气次数每小时不小于( )次计算。...
  14. 驾考——科一,三笔记
  15. python(输入)正常返回否则出错重新
  16. 一路编程,一路迷茫,一路醒悟,接着迷茫,再醒悟再迷茫
  17. pc端双六边形重叠效果(带边框的六边形)
  18. 写了placement new也要写placement delete——条款52
  19. 怎么把计算机里的文件放到桌面上,ipad怎么把文件放到桌面
  20. win10 icc文件路径

热门文章

  1. 【Multi-Step TD Target】TD算法的改进
  2. GNU系统下内存对齐分配的记录
  3. 从后端看Vue-读《Vue.js技术内幕》
  4. 图像超分辨率 之 GLEAN论文解读与感想
  5. 2021年陕西省安全员C证考试题及陕西省安全员C证试题及解析
  6. 建模助手(Revit)插件如何生成基坑开挖和地下连续墙?
  7. 厉害了!和网易大佬的技术面谈,大厂直通车!
  8. 数聚智连IPO过会:年营收17.7亿 险峰、蓝标及高榕是股东
  9. 解决Maven离线下载中心仓库连接失败问题
  10. HarmonyOS DevEcoStudio 运行远程模拟器 提示The HDC tool hasn‘t been installed. Download the toolchains agains