数据结构课程设计——项目2:校园导游咨询(图 Dijkstra算法寻找最短路径)
一、问题描述和项目要求
1.1 问题描述
设计一个校园导游程序,为来访的客人提供各种信息查询服务。
1.2 基本要求
(1) 设计你所在学校的校园平面图,所含景点不少于10个.以图中顶点表示校内各景点,存放景点名称、代号、简介 等信息;以边表示路径,存放路径长度等相关信息。
(2) 为来访客人提供图中任意景点相关信息的查询。
(3) 为来访客人提供图中任意景点的问路查询,即查询任意两个景点之间的一条最短的简单路径。
二、问题分析
2.1 程序功能设计分析
1)能够查看所有的景点信息
2)能够查看指定景点的详细信息
3)能够找到当前所在地到目的地的最短路径
4)图的信息存入系统,使用时能直接读取
2.2 程序实现分析
使用一个顶点类的数组存放顶点信息,如下:
class Node {
String name;
String introduction;
}
// 存放顶点信息
Node[] vertex = new Node[100];
使用邻接矩阵存放边的信息,如下:
/**
* 邻接矩阵,对于adj[i][j]:
* 若i=j,adj[i][j]=0
* 若i!=j,且顶点i与j有一条边,adj[i][j]=边的长度
* 若i!=j,且顶点i与j无边连接,adj[i][j]=Integer.MAX_VALUE
*/
int[][] adj = new int[100][100];
三、逻辑设计
3.1 抽象数据类型的定义
程序整体的抽象数据类型定义
ADT MGragh
Data:
邻接矩阵
存放顶点信息的定点类数组
顶点个数
边的个数
Operation:
printAllVertex
输入: 无
输出: 输出所有景点的信息
返回: 无
Dijkstra// 迪杰斯特拉算法求最短路径
输入: 起始顶点v0,记录起始顶点到各个顶点最短距离的数组dist,记录到每个顶点最短路径的前序顶点的数组path
输出: 无
返回: 无
minPath
输入: 起始顶点v0,目标顶点v
输出: 输出从v0到v的最短路径
返回: 无
find
输入: 指定的顶点n
输出: 输出指定顶点的详细信息
返回: 无
endADT
3.2 程序方法调用关系图
四、主要方法的算法设计
Dijkstra算法
1)使用邻接矩阵表示带权图,设V为所有的顶点集,设S为已找到最短路径的终点集合,初态S={v0},其中v0为起点,设v0下标为i,用数组dist的每个分量dist[j]记录从v0到vj的最短路径长度,初始时,dist[i]= 0,dist[j] = adj[i][j],adj为邻接矩阵。
2)选择一个vk使得dist[k]=min{ dist[j]| vj∈V-S },则vk就是求得的一条从v0出发的最短路径终点,令S=S∪{ vk }。
3)修改dist[u],其中u∈V-S,u!=k。
若dist[j] + adj[k][u] < dist[u],修改dist[u] = dist[j] + adj[k][u]。
4)重复步骤2和3 n-1次,即可求得从v0到各个顶点的最短路径。
5)为了寻路,还应记录每条最短路径的各个顶点,需设一个整形数组path,path[j]的值为到达v[j]的当前最短路径长度的前驱顶点下标 ,初始时path[j] 的值应为:
5.1 当i=j,path[j] =-1
5.2 当i!=j,i与j不领接时,path[j] =-1
5.3 当i!=j,i与j领接时,path[j] = adj[i][j]
6)因为到达v[j]的前驱顶点的路径长度也是最短的,所以通过path[j],path[ path[j] ],…,i即可追踪出由v0到vj的最短路径所经顶点,所以path中存储了从v0到到各个顶点的最短路径信息。输出时由于path是逆序寻路需要一个栈来辅助输出。
7)算法使用了一个数组S记录各个顶点是否已在集合S中。
java源码如下:
/**
* 找到v0到各个顶点的最短路径
* @param v0 起始顶点的编号
* @param dist dist[j] 为寻找过程中从v0到vj的当前最短路径长度
* @param path path[j]的值为到达vj的当前最短路劲长度的前驱顶点下标
*/
void Dijkstra(int v0,int dist[],int path[]){
// dist和path分别记录从v0到每个顶点的最短路径长度和路径
int i,k,min;
int []S=new int[vertexNum+1];//记录该顶点是否求得最短路径长度
for(i=1;i<=vertexNum;i++){
// 初始化dist和path
dist[i]=adj[v0][i];
if(dist[i]!=Integer.MAX_VALUE) path[i]=v0;
else path[i]=-1;
}
path[v0]=-1;
dist[v0]=0;
S[v0]=1;// 标记v0起点不用再寻找
int num=1;
while (num<vertexNum){
k=0;
min=Integer.MAX_VALUE;
for(i=1;i<=vertexNum;i++){
// 找到新的最短边
if(S[i]!=1&&dist[i]<min){
min=dist[i];
k=i;
}
}
S[k]=1;// 标记k顶点已找到最短路径
for(i=1;i<=vertexNum;i++){
// 更新dist和path
if(adj[k][i]!=Integer.MAX_VALUE){
if(S[i]!=1&&dist[i]>dist[k]+adj[k][i]){
dist[i]=dist[k]+adj[k][i];
path[i]=k;
}
}
}
num++;
}
}
/**
* 输出从v0到v的最短路径信息
* @param v0 起始顶点
* @param v 终点
*/
void minPath(int v0,int v){
int []dist=new int[vertexNum+1];
int []path=new int[vertexNum+1];
Dijkstra(v0,dist