标签:control reads generate 灵活 contains readline tostring add nal
1.该程序能够准确地读出.txt文件中的数据,文件格式简洁易懂、可灵活扩展
2.在某号线路上,能够查询各个站点的信息,输出该号线路上所有站点信息
3.在出发站与目的站之间输出一个最短路径

一共三个package:control、main、model

control包里有Dijkstra.java,distance.java
Dijkstra.java(此代码为最短路径算法,这是最核心最难的地方,dijkstra算法能很好地解决最短路径问题,这段代码是借鉴了网上的代码,但是我还没能理解透彻):
package control;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import model.*;
public class Dijkstra {
private static HashMap<station, lujing> h = new HashMap<>();
private static List<station> l = new ArrayList<>();
public static lujing calculate(station star, station end) {
if (!l.contains(star)) {//将开始站点加入到分析过的站点集合。
l.add(star);
}
if (star.equals(end)) {//如果开始站点等于终止站点,则设置result,设置距离和station。
lujing lujing = new lujing();
lujing.setDistance(0.0D);
lujing.setEnd(star);
lujing.setStart(star);
return h.put(star, lujing);
}
if (h.isEmpty()) {//第一次调用calculate,且起始点和终止点不同,则h为空。
List<station> ls = getLinkStations(star); //第一次调用获取起始点的相邻站点(在所有地铁线中,这里涉及转线交叉的周围站点)
for (station station : ls) {//把相邻站点集合中的所有站点,加入h中。 因为相邻,则可以直接获取Distance。
lujing lujing = new lujing();
lujing.setStart(star);
lujing.setEnd(station);
String key = star.getSname() + ":" + station.getSname();
lujing.setDistance(1.0);
lujing.getPassStations().add(station);
h.put(station, lujing);
}
}
station parent = getNextStation();
if (parent == null) { //如果h所有点keySet被分析完了,则返回的parent为null。
lujing lujing = new lujing();
lujing.setDistance(0.0D);
lujing.setStart(star);
lujing.setEnd(end);
return h.put(end, lujing);//put方法的返回值就是value值。
}
if (parent.equals(end)) {//如果得到的最佳邻点与目标点相同,则直接返回最佳邻点对应的result对象。
return h.get(parent);
}
//在路径经过点中加入parent后,更新h集合,要么起始点经过parent达到parent相邻点是最优的,要么起始点到parent相邻点不可达,而通过parent可达。
//获取parent对象(最佳点)的相邻点。
//分析一个parent最佳点后,把它的相邻点都会加入到h中,在下一次调用getNextStation获取h中未被标记且距离(起始点到该station的距离)最短。
List<station> childLinkStations = getLinkStations(parent);
//D:B C E
for (station child : childLinkStations) {
if (l.contains(child)) {
continue;
}
String key = parent.getSname() + ":" + child.getSname();
Double distance;
if (parent.getSname().equals(child.getSname())) {
distance = 0.0D;
}
Double parentDistance = h.get(parent).getDistance();
distance = parentDistance+1.0;
List<station> parentPassStations = h.get(parent).getPassStations();
lujing childResult = h.get(child);
if (childResult != null) {
if (childResult.getDistance() > distance) {
childResult.setDistance(distance); //如果通过最佳点比直接到距离小,则更新h中的对应result对象。
childResult.getPassStations().clear();
childResult.getPassStations().addAll(parentPassStations);//路径更新为A->最佳点->child点。
childResult.getPassStations().add(child);
}
} else {
childResult = new lujing();//如果在h中没有最佳点的相邻点,则往h中添加通过最佳点(初始为起始点的最佳邻点)到达该点。
childResult.setDistance(distance);
childResult.setStart(star);
childResult.setEnd(child);
childResult.getPassStations().addAll(parentPassStations);
childResult.getPassStations().add(child);
}
h.put(child, childResult);
}
//初始时,即第一次调用该方法时,在分析点中加入起始点的最佳相邻点,后面嵌套调用时,就为获取某点的最佳邻点,在用最佳邻点更新h后,往l中加入最佳邻点。
l.add(parent);
//加入最佳邻点后,更新h,再次调用calculate
return calculate(star, end);
//或:
// calculate(star, end); 继续往下走,选择最佳点,然后更新h。
// return h.get(end);
}
public static List<station> getLinkStations(station station) { //传入起始点station对象。
List<station> linkedStaions = new ArrayList<station>();
for (List<station> line : distance.lset) {
for (int i = 0; i < line.size(); i++) {//遍历每条地铁线,若地铁线中存在该站点,则判断,如果该站点位于地铁线的起始站,则相邻站为地铁线的第二个站点(i+1),
//如果该站点位于地铁线的最后一个站,则相邻站为地铁线的倒数第二个站点(i-1),
//如果该站点位于地铁线的其余位置,则相邻站点为该站点前后位置(i-1/i+1)
if (station.equals(line.get(i))) {
if (i == 0) {
linkedStaions.add(line.get(i + 1));
} else if (i == (line.size() - 1)) {
linkedStaions.add(line.get(i - 1));
} else {
linkedStaions.add(line.get(i + 1));
linkedStaions.add(line.get(i - 1));
}
}
}
}
return linkedStaions;
}
private static station getNextStation() {//获取最短路径距离
Double min = Double.MAX_VALUE;
station rets = null;
Set<station> stations = h.keySet();//获取h中的station集合。
for (station station : stations) {
if (l.contains(station)) {//如果该点被标记为“已被分析”(已被分析表示起始点到该点的最短路径已求出)
continue;
}
lujing result = h.get(station);//循环分析h中未被标记的点,求出最短路径的result对象。
if (result.getDistance() < min) {
min = result.getDistance();
//得到终点的station对象
rets = result.getEnd();
}
}
return rets;
}
private static double doubleAdd(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
public static void getResultToText(String filePath) throws IOException {
if (filePath == null) {
throw new FileNotFoundException("兄弟来个路径保存路径吧");
}
BufferedWriter writer = null;
//追加路径信息...
writer = new BufferedWriter(new FileWriter(filePath, true));
Set<List<station>> lineSet = distance.lset;
for (List<station> stations : lineSet) {
for (station station : stations) {
for (List<station> stations2 : lineSet) {
for (station stationTarget : stations2) {
Dijkstra d = new Dijkstra();
lujing lujing = d.calculate(station, stationTarget);
h = new HashMap<>();
l = new ArrayList<>();
for (station s : lujing.getPassStations()) {
if (s.getSname().equals(stationTarget.getSname())) {
String text = station.getSname() + "\t" + stationTarget.getSname() + "\t" + lujing.getPassStations().size() + "\t" + lujing.getDistance() + "\t";
for (station test : lujing.getPassStations()) {
text = text + test.getSname() + ",";
}
writer.write(text);
writer.newLine();
}
}
}
}
}
}
writer.flush();
writer.close();
}
}
distance.java:
通过站点名称获取线路信息:
public static String getLineName(station station){
createlineData();
String startname = station.getSname();
for (Map.Entry<String,List<station>> entry : ldata.entrySet()) {
List<station> stations = entry.getValue();
for (station sta : stations){
if(sta.getSname().equals(startname)){
return entry.getKey();
}
}
}
return "";
}
获取线路信息:
public static ArrayList<station> getLine(String l1,String l2){
ArrayList<station> l = new ArrayList<station>();
String[] a = l1.split(",");//每个站点之间用逗号分隔
for (String s : a) {
l.add(new station(s,l2));
}
return l;
}
写入线路数据:
public static String writeLineData(String lname){
createlineData();
lname = lname.substring(0,1);
List<station> a = ldata.get(lname);
String lstr = a.stream().map(x->x.getSname()).collect(Collectors.joining(","));
try {
Files.write(Paths.get(writedis), lstr.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
return lstr;
}
输出最短线路:
public static void shortline(lujing l){
FileWriter a= null;
BufferedWriter b = null;
try {
a = new FileWriter(new File(writedis),true);
b = new BufferedWriter(a);
b.write((l.getPassStations().size()+1) + "\t\n");//写入总站数
b.write(l.getStart().getSname() + "\t\n");//写入起点站
String startlname = getLineName(l.getStart());//通过起点站名称得到线路名
String c = startlname;
for (station station : l.getPassStations()){
if(!c.equals(station.getLname())){
b.write(station.getLname()+"号线" + "\t\n");//写入转乘站名
b.write(station.getSname()+ "\t\n");
c = station.getLname();
}else{
b.write(station.getSname() + "\t\n");
}
}
a.close();
b.close();
} catch (IOException e) {
e.printStackTrace();
}
}
读取文件:
public static void readinformation() {
File file = new File(readdis);
BufferedReader reader = null;
try {
InputStreamReader i = new InputStreamReader(new FileInputStream(file), "UTF-8");
reader = new BufferedReader(i);
String l = null;
String lname = "1";
while ((l = reader.readLine()) != null) {
if (l.trim().startsWith("*")) {
String[] a = l.substring(1).split("-");
lset.add(getLine(a[1].trim(), a[0].trim()));
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
输出线路信息:
public void readwj(){
try {
FileReader f = new FileReader("station.txt");
BufferedReader b = new BufferedReader(f);
String str=b.readLine();
while(str!=null) {
System.out.println(str);
str=b.readLine();
}
f.close();
b.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("文件不存在");
}
}
输出最短路径:
public void readshort(){
try {
FileReader f = new FileReader("routine.txt");
BufferedReader b = new BufferedReader(f);
String str=b.readLine();
while(str!=null) {
System.out.println(str);
str=b.readLine();
}
f.close();
b.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("文件不存在");
}
}
}
model包里有lujing.java,station.java
lujing.java(是对于路径上站点变量函数的存储结构):
package model;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class lujing {
private station start;//起点
private station end;//终点
private Double distance = 0.0D;//站点距离
private List<station> passStations = new ArrayList<>();//经过的站点
public station getStart() {
return start;
}
public void setStart(station start) {
this.start = start;
}
public station getEnd() {
return end;
}
public void setEnd(station end) {
this.end = end;
}
public Double getDistance() {
return distance;
}
public void setDistance(Double distance) {
this.distance = distance;
}
public List<station> getPassStations() {
return passStations;
}
public void setPassStations(List<station> passStations) {
this.passStations = passStations;
}
}
station.java(是对于线路上变量函数的存储结构):
package model;
import java.util.ArrayList;
import java.util.List;
public class station {
private String sname; // 站点名称
private String lname; // 所属线路名称
private List<station> lstation = new ArrayList<>(); //相邻连接的站点
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public List<station> getLstation() {
return lstation;
}
public void setLstation(List<station> lstation) {
this.lstation = lstation;
}
public station(String sname, String lname) {
this.sname = sname;
this.lname = lname;
}
public station(String sname) {
this.sname = sname;
}
}
main包里有subway.java
subway.java:
package main;
import java.io.File;
import java.io.IOException;
import control.Dijkstra;
import control.distance;
import model.lujing;
import model.station;
public class subway {
public static void main(String[] args) throws IOException {
distance d=new distance();
switch (args[0]){
case "-map":
if(args.length==2){
distance.readdis=System.getProperty("user.dir") + File.separator + "\\" + args[1];
distance.readinformation();
System.out.println("成功读取subway.txt文件");
}else{
System.out.println("读取错误");
}
break;
case "-a":
if(args.length==6){
distance.readdis = System.getProperty("user.dir") + File.separator + "\\" + args[3];
distance.writedis = System.getProperty("user.dir") + File.separator + "\\" + args[5];
distance.readinformation();
distance.writeLineData(args[1]);
System.out.println("线路站点:");
d.readwj();
}else{
System.out.println("读取错误");
}
break;
case "-b":
if(args.length==7){
distance.readdis = System.getProperty("user.dir") + File.separator + "\\" + args[4];
distance.writedis = System.getProperty("user.dir") + File.separator + "\\" + args[6];
distance.readinformation();
lujing l = Dijkstra.calculate(new station(args[1]), new station(args[2]));
d.shortline(l);
System.out.println("最短线路:");
d.readshort();
}else{
System.out.println("读取错误");
}
break;
}
}
}
需求1:读取subway.txt文件的语句:
java subway -map subway.txt
需求2:输出指定线路的所有站点
java subway -a 1号线 -map subway.txt -o station.txt
需求3:输出两站点之间的最短路径
subway.exe -b 洪湖里 复兴路 -map subway.txt -o routine.txt
由于是首次做一个感到如此艰难的个人项目,相比于暑期的短学期项目,这个明显难了很多,对于个人能力要求上了不止一个大档次。其次,刚开始写代码,一直卡在最短路径算法这个方向,后来想到了dijkstra算法,但是对这个算法又并没有那么熟悉,所以在这个个人项目中,借鉴了网上的算法代码,但是,在参考了代码之后,一直看的糊糊涂涂,了解了之后也并没有能学以致用,这是对于自己一个失望的地方。
标签:control reads generate 灵活 contains readline tostring add nal
原文地址:https://www.cnblogs.com/lssyzyy/p/11674613.html