2024.4.9

所学时间:2小时

代码行数:81

博客园数:1篇

所学知识:我的结对作业伙伴是张雨锟,我们今天写迪杰斯特拉算法,用来解决最短路径问题,定义了一个名为Dijkstra的类,其中包含了计算最短路径的静态方法calculate和一些辅助方法。类中使用了HashMap<Station, Result> result来存储每个站点到目标站点的最短距离和路径信息。visitedStations列表用于记录已经访问过的站点。calculate方法接收起始站点和目标站点作为参数,然后根据Dijkstra算法计算出起始站点到目标站点的最短路径。getLinkStations方法用于获取与给定站点相邻的站点列表。getNextStation方法用于获取下一个要处理的站点,即距离起始站点最近且未被访问过的站点。通过测试最终完成了。

package com.example.niumo67.Subway;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

public class Dijkstra {
// 最短路径集合
private static HashMap<Station, Result> shortestPath = new HashMap<>();
// 已经分析过的站点集合
private static List<Station> visitedStations = new ArrayList<>();

public static Result calculate(Station startStation, Station endStation) {
// 第一次使用calculate方法时将起点站添加到已分析集合里去
if (!visitedStations.contains(startStation)) {
visitedStations.add(startStation);
}
// 如果起点站和终点站相同,则返回经过0站
if (startStation.equals(endStation)) {
Result result = new Result();
result.setDistance(0);
result.setStartStation(startStation);
result.setEndStation(startStation);
return shortestPath.put(startStation, result);
}
// 第一次使用calculate方法时shortestPath集合才为空,此时将起点站的临近站点全加入到shortestPath集合
if (shortestPath.isEmpty()) {
List<Station> linkStations = getLinkStations(startStation);
for (Station s : linkStations) {
Result result = new Result();
result.setStartStation(startStation);
result.setEndStation(s);
result.setDistance(1);
result.getPassStations().add(s);
shortestPath.put(s, result);
}
}
// 获取下一个最佳站点
Station nextStation = getNextStation();
if (nextStation == null) {
System.out.println("这种情况绝对不可能出现!");
}
// 最佳站点是终点站的时候,代表最短路径已经搞定了
if (nextStation.equals(endStation)) {
return shortestPath.get(nextStation);
}
// 获取最佳站点的临近站点,并将最佳站点加入到shortestPath集合里,更新最短路径
List<Station> nextStationLinkStations = getLinkStations(nextStation);
for (Station linkStation : nextStationLinkStations) {
if (visitedStations.contains(linkStation)) {
continue;
}
// 因为在原路径上加入最佳站点,所以距离+1
int distance = shortestPath.get(nextStation).getDistance() + 1;
// 获取最佳点经过的站点
List<Station> nextStationPassStations = shortestPath.get(nextStation).getPassStations();
Result linkStationResult = shortestPath.get(linkStation);
// linkStationResult非空的意思是,现最短路径中有最佳点的邻接站点
// 举个例子:现最短路径为:startStation->...->linkStation
if (linkStationResult != null) {
// 接上例子,startStation->...->linkStation这条路径长度为9,startStation->...->nextStation的长度为7
// 则更新最短路径:startStation->...->nextStation->linkStation
if (linkStationResult.getDistance() > distance) {
linkStationResult.setDistance(distance);
linkStationResult.getPassStations().clear();
linkStationResult.getPassStations().addAll(nextStationPassStations);
linkStationResult.getPassStations().add(linkStation);
}
}
// 如果最近路径中无最佳站点的临近站点,则把最近站点添加到最短路径中。startStation->...->nextStation
else {
linkStationResult = new Result();
linkStationResult.setDistance(distance);
linkStationResult.setStartStation(startStation);
linkStationResult.setEndStation(linkStation);
linkStationResult.getPassStations().addAll(nextStationPassStations);
linkStationResult.getPassStations().add(linkStation);
}
shortestPath.put(linkStation, linkStationResult);
}
// 将最佳点添加到已分析的集合中
visitedStations.add(nextStation);
return calculate(startStation, endStation);
}

// 获取所有的邻接站点
public static List<Station> getLinkStations(Station station) {
List<Station> linkStations = new ArrayList<>();

for (SubwayLine line : GetInfo.lines) {
for (int i = 0; i < line.stations.size(); i++) {
if (station.equals(line.stations.get(i))) {
if (i == 0) //i=0的时候是总站,若想最短路径不要经过总站,改为i==1即可
linkStations.add(line.stations.get(i + 1));
else if (i == (line.stations.size() - 1))
linkStations.add(line.stations.get(i - 1));
else {
linkStations.add(line.stations.get(i - 1));
linkStations.add(line.stations.get(i + 1));
}
}
}
}
return linkStations;
}

// 获取下一个最佳站点
public static Station getNextStation() {
int min = 10000;
Station nextStation = null;
Set<Station> stations = shortestPath.keySet();
for (Station s : stations) {
if (visitedStations.contains(s))
continue;
Result r = shortestPath.get(s);
// 比较最短路径中没有被分析过的点,找出路径最短的站点
if (r.getDistance() < min) {
min = r.getDistance();
nextStation = s;
}
}
return nextStation;
}

public static void reset() {
visitedStations.clear();
shortestPath.clear();
}
}


package com.example.niumo67.Subway;

import java.io.*;
import java.sql.*;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

public class GetInfo {
// 存储线路上的站点信息
public static List<SubwayLine> lines = new ArrayList<>();
// 存储相邻站点
public static List<Station> stations = new ArrayList<>();
private static GetInfo getInfo;
public static GetInfo getGetInfo() throws SQLException, ClassNotFoundException {
if (getInfo==null)
{
getInfo=new GetInfo();
getInfo.subwayMap();
}
return getInfo;
}
public static void subwayMap() throws ClassNotFoundException, SQLException {


String f = "D:\\ideaaa\\NIUMO67\\subway.txt";
try {
// FileReader用于读取文件字符流
FileReader r = new FileReader(f);
// BufferedReader类从字符输入流中读取文本并缓冲字符
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f),"UTF-8"));
String line;
// 分离每一条线路
while((line = br.readLine()) != null) {
System.out.println(line);
// 分离线路名称
String[] tokens = line.split("/",2);
SubwayLine s1 = new SubwayLine();
// tokens[0]是线路名称
s1.name = tokens[0];
// 分离票价
String[] tokens1 = tokens[1].split("%",2);
s1.fare = Double.parseDouble(tokens1[0]);
// 分离首末班时间
String[] ftime = tokens1[1].split("%",2);
s1.FirstTime = s1.simpleDateFormat.parse(ftime[0]);
String[] ltime = ftime[1].split("-",2);
s1.LastTime = s1.simpleDateFormat.parse(ltime[0]);
// 分离各个站点
String[] tokens2 = ltime[1].split(" ");
// forEach循环,字符串s每次获取一个站点信息
for(String s: tokens2) {
Station station = new Station();
// 判断该站点是否可换乘
boolean isTransfer = s.contains("#");
if(isTransfer) {
station.isTransferStation = true;
// 分离换乘站信息
String[] tokens3 = s.split("#");
station.name = tokens3[0];
// 解析该站点可换成的线路
for(int i = 1; i < tokens3.length; i++) {
if(tokens3[i].equals("1"))
station.lines.add("1号线");
else if(tokens3[i].equals("2"))
station.lines.add("2号线");
else if(tokens3[i].equals("4"))
station.lines.add("4号线");
else if(tokens3[i].equals("5"))
station.lines.add("5号线");
else if(tokens3[i].equals("6"))
station.lines.add("6号线");
else if(tokens3[i].equals("7"))
station.lines.add("7号线");
else if(tokens3[i].equals("8北"))
station.lines.add("8号线北");
else if(tokens3[i].equals("8南"))
station.lines.add("8号线南");
else if(tokens3[i].equals("9"))
station.lines.add("9号线");
else if(tokens3[i].equals("10"))
station.lines.add("10号线");
else if(tokens3[i].equals("13"))
station.lines.add("13号线");
else if(tokens3[i].equals("14西"))
station.lines.add("14号线西");
else if(tokens3[i].equals("14东"))
station.lines.add("14号线东");
else if(tokens3[i].equals("15"))
station.lines.add("15号线");
else if(tokens3[i].equals("16"))
station.lines.add("16号线");
else if(tokens3[i].equals("八通"))
station.lines.add("八通线");
else if(tokens3[i].equals("房山"))
station.lines.add("房山线");
else if(tokens3[i].equals("昌平"))
station.lines.add("昌平线");
else if(tokens3[i].equals("亦庄"))
station.lines.add("亦庄线");
else if(tokens3[i].equals("燕房"))
station.lines.add("燕房线");
else if(tokens3[i].equals("S1"))
station.lines.add("S1线");
else if(tokens3[i].equals("西郊"))
station.lines.add("西郊线");
else if(tokens3[i].equals("首都机场"))
station.lines.add("首都机场线");
}
}
else {
if(s.contains("!")) {
continue;
}
station.isTransferStation = false;
station.name = s;
}
// 该站点所在线路
station.line = tokens[0];
// 添加途径站点
stations.add(station);
// 为该线路添加站点
s1.stations.add(station);
}
lines.add(s1);
}

} catch (IOException | ParseException ex) {
ex.printStackTrace();
}
}
/*
public static String getLineName(Station station) {
for(SubwayLine s : lines) {
for(Station st : s.stations) {
if(st.name.equals(station.name)) {
return st.line;
}
}
}
return "";
}
*/
}
posted @ 2024-04-09 20:58  kuku睡  阅读(8)  评论(0编辑  收藏  举报