个人项目——地铁线路

个人git

一、项目需求

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算法,但是对这个算法又并没有那么熟悉,所以在这个个人项目中,借鉴了网上的算法代码,但是,在参考了代码之后,一直看的糊糊涂涂,了解了之后也并没有能学以致用,这是对于自己一个失望的地方。

原文地址:https://www.cnblogs.com/lssyzyy/p/11674613.html

时间: 2024-08-30 16:21:32

个人项目——地铁线路的相关文章

个人项目——地铁线路规划

个人项目-地铁线路规划系统 GitHub项目地址:https://github.com/ye1014239226/Subway1.git 问题描述 1.输入地铁线路的名字,显示该线路上的站点信息 2.输入起末站的站点名字,输出最优的换乘路线(经过站点数量最少) 解决思路 1.收集北京地铁的线路信息,存入txt文件中,并导入到设计的数据存储方式中去 2.读入数据并且构建地铁线路图的数据结构 3.使用迪杰斯特拉算法求最短的换乘路径 4.测试 解决过程 1.数据存储 txt的存储形式如下 线路名 站点

个人项目——地铁线路的最短路径

地铁路线规划的初步分析 支持环境 windows7, 10, macOS, linux 需求分析 1.读取一定格式下的地铁信息文件 2.提供详细的地铁信息的查询 3.提供最短路的计算与推荐功能:路线最短,时间最短,换地铁数最少... 4.UI展示 设计实现 1.基本线路设计表(概念设计如下): 开始时只保存同一站点下相邻的站点 最后生成站点间两两的最优路线 初始信息表: 出发站点 目的站点 经过地铁 肿瘤医院 天津宾馆 5号线.6号线 大王庄 十一经路 9号线 大学城 王顶堤 3号线 大毕庄 南

个人项目-地铁出行线路规划程序

PSP表格 PSP 2.1 Personal Software Process Stages Planning Time(H) Used Time(H) Planning 计划 0.5 0.25 · Estimate · 估计这个任务需要多少时间 0.5 0.25 Development 开发 25.5 45.9 · Analysis · 需求分析 (包括学习新技术) 10 13 · Design Spec · 生成设计文档 2 3 · Design Review · 设计复审 (和同事审核设计

地铁线路项目-结对编程

地铁线路项目-结对编程 2019.7.25 完成了模块开发:填写PSP实际完成时间:完成了模块设计:进行单元测试.黑盒测试. PSP表记录: PSP2.1 Personal Software Process Stages Time Real Time Planning 计划 1h 1h ??·?Estimate ?? ·?估计这个任务需要多少时间 1h 1h Development 开发 21h 20.5h ??·?Analysis ?? ·?需求分析?(包括学习新技术) 2h 1.5h ??·

天津地铁线路最短路径计算项目规划

天津地铁线路路径查询项目规划 一.项目介绍 实现一个帮助进行地铁出行路线规划的命令行程序. 二.项目完成预估表 PSP 2.1 Personal Software Process Stages Time Time Planning 计划 · Estimate · 估计这个任务需要多少时间 1day Development 开发 · Analysis · 需求分析 (包括学习新技术) 3day · Design Spec · 生成设计文档 1day · Design Review · 设计复审 (

个人项目1(地铁线路最短路径的程序)初步分析

1.需求分析 根据个人项目简介,软件的需求有以下三个: 需求1: 实现一个支持显示地铁线路与计算换乘的程序.之后,用户可以通过命令行启动这个程序.程序在启动时,会读取不同命令对应的命令行参数.对于地铁线路信息图,我们约定它采用参数 -map 作为标志.程序启动时需要通过读取 -map 参数来获得对应的自定义地铁文件(命名为 subway.txt),从而得到地铁线路图的信息. 需求2: 实现基础的查询操作.比如说,用户希望查询指定地铁线经过的站点.这样,在应用程序需要支持一个新的命令行参数 -a,

地铁线路项目需求分析

地铁线路项目需求分析 需求分析 1.如何设计读取的文档格式. 2.根据输入的线路获得该线路上的所有站点信息. 3.输入一个起点站一个终点站,能够输出它们之间最短距离所经过的站点数以及站点名称. 4.测试以及性能的检测 5.各环节所需时间 计划阶段 时间 计划 估计此任务所需时间 开发 需求分析 生成设计文档 设计复审 代码规范 具体设计 具体编码 代码复审 测试 报告 测试报告 计算工作量 事后总结 总计 设计思路 题目的主要要求是如何读取数据以及根据用户需要输出站点信息. 在文档中,每行先输入

个人项目——北京地铁线路规划

一.前言 现实和理想的差距总是那么大,在过程中碰到的坑比预期的还多(说那么多,其实就是自己菜),过程中复习了淡忘已久的许多算法和数据结构,一边深刻的体会着自己是多菜,一边也体会到了自身一点点微小的进步,大概. 二.项目简介 实现北京地铁查询功能 附上一张北京地铁的图: 三.项目地址 https://github.com/fireworks-EX/MetroLinePlanning 四.需求分析 1.确定储存及读取地铁线路数据文件的格式 2.支持用户输入的地铁线路的查询 3.提供用户指定两站点间的

个人项目关于北京地铁线路出行线路规划

一  问题重述 1.实现地铁线路的加载 2.实现查询指定线路所有站点(包括换乘信息) 3.实现查询指定两个站点间的最短路径 二  功能设计 1.实现地铁线路的加载 -map subway.txt //将存储在subway.txt文件里的地铁线路进行读取 2.实现查询指定线路所有站点 -a 地铁线路名称 -map subway.txt -o station.txt //读取subway.txt文件信息后,通过输入的地铁线路名称,将指定地铁线路的所有站点写入station.txt文件 3.实现查询指