公交系统的java实现(伍)

        上集中写到,一次换乘有很多重复数据,所以要增加这样的去重逻辑:

         如果某站点上次被处理过,并且上次处理的换乘路线和这次的换乘路线相同,并且总站数没有减少,则认为该站点不应被再次处理。

          举个例子:  从A站点到C站点,线路1是直接1路直达,座5站就到,线路2是中转B站,2路,然后再坐1路,到C站。这时候,线路2中C站点上次处理的线路名称也是1路,所以查看线路2的总站数。如果线路2的总站数小于5站,那么认为线路2是一条新线路。如果线路2总站数大于或等于5站,则认为是一条废线路,不做处理。   

       代码为:

package graph;

/**  
 *  DelRepeat 去重需要的类
 * @author xuejupo  [email protected] 
 * create in 2015-12-7 下午6:34:09    
 */

public class DelRepeat implements Comparable{
	public DelRepeat(String standName, int num, int standNum,String lineName){
		this.standName = standName;
		this.num = num;
		this.standNum = standNum;
		this.lineName = lineName;
	}
	
	//站名
	String standName;
	//需要换乘次数
	int num;
	//总共需要的站数
	int standNum;
	//上次换乘的线别
	String lineName;
	/**
	 * 重写比较方法,当换乘次数和换乘站数都大的话,则认为该站点不用再次处理
	 */
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		DelRepeat d = (DelRepeat)o;
		if(!this.standName.equals(d.standName)){
			return -1;
		}
		if(d.num > this.num && d.standNum > this.standNum){
			return 1;
		}
		//当需要换乘更多次数,但是总站数不少的情况下,认为不应该加入到线路中
		if(d.num > this.num && d.lineName.equals(this.lineName) && d.standNum >= this.standNum){
			return 1;
		}
		return -1;
	}
	/**
	 * 要往set里放,重写equal方法和tohash方法
	 */
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return this.standName.hashCode();
	}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		DelRepeat d = (DelRepeat)obj;
		return this.standName.equals(d.standName);
	}
	
}

         获取两站之间最短距离的代码:(只获取最多换乘2次的情况)

package graph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Transit :
 * 
 * @author xuejupo [email protected] create in 2015-12-4 下午7:08:40
 */

public class Transit {

	//保存线路,去掉重复
	static Set<List<Line>> hasDoneLine = new HashSet<List<Line>>();
	Map<String,DelRepeat> isNeedDeal = new HashMap<String,DelRepeat>();
	// 第一层的结果
	List<Line> firstLevel = new ArrayList<Line>();

	// 第二层的结果
	List<Map<String, List<Line>>> secondLevel = new ArrayList<Map<String, List<Line>>>();

	// 第三层的结果
	List<Map<String, List<Line>>> thirdLevel = new ArrayList<Map<String, List<Line>>>();

	// 第四层的结果
	private List<Map<String, List<Line>>> forthLevel = new ArrayList<Map<String, List<Line>>>();

	/**
	 * existStand:用于处理已处理节点是否应该再次处理
	 * 
	 * @author xuejupo [email protected] create in 2015-12-4 下午8:15:46
	 * 
	 */
	class existStand implements Comparable {
		/**
		 * @Fields totalNum : 总共的站数
		 */
		int totalNum;
		/**
		 * @Fields midNum : 一共中转的站数
		 */
		int midNum;

		@Override
		public int compareTo(Object o) {
			// TODO Auto-generated method stub
			existStand e = (existStand) o;
			if (e.totalNum <= this.totalNum && e.midNum <= this.midNum) {
				return -1;
			}
			return 1;
		}
	}
	public void initlevel(String from){
		Set<String> firSet = this.getFirstLevel(from);
		//利用融合的方法取第二层和第三层数据
		getLevelData(from,getLevelData(from, firSet, secondLevel),thirdLevel);
	}
	

	/**  
	* getFirstLevel: 处理第一层的结果
	* @param from
	* @return 
	* Set<String>  返回类型   
	*/
	private Set<String> getFirstLevel(String from) {
		Set<String> s = new HashSet<String>();
		firstLevel = getLineList(from, from,s);
		return s;
	}

	/**  
	* getSecondLevel: 处理第二层的结果
	* @param from
	* @param set
	* @return 
	* Set<String>  返回类型   
	*/
	private Set<String> getSecondLevel(String from,Set<String> set){
		Set<String> second = new HashSet<String>();
		//处理第一层所有的站点
		for(String stand:set){
			Set<String> s = new HashSet<String>();
			Map<String, List<Line>> m= new HashMap<String, List<Line>>();
			m.put(stand, this.getLineList(stand, from, s));
			secondLevel.add(m);
			//把第二层可达站点放入set中,供第三层取用
			second.addAll(s);
		}
		return second;
	}
	
	/**  
	* getSecondLevel: 处理第三层的结果
	* @param from
	* @param set
	* @return 
	* Set<String>  返回类型   
	*/
	private Set<String> getThirdLevel(String from,Set<String> set){
		Set<String> second = new HashSet<String>();
		//处理第二层所有的站点
		for(String stand:set){
			Set<String> s = new HashSet<String>();
			Map<String, List<Line>> m= new HashMap<String, List<Line>>();
			m.put(stand, this.getLineList(stand, from, s));
			thirdLevel.add(m);
			//把第三层可达站点放入set中,供第四层取用
			second.addAll(s);
		}
		return second;
	}
	
	/**  
	* getSecondLevel: 处理第四层的结果
	* @param from
	* @param set
	* @return 
	* Set<String>  返回类型   
	*/
	private Set<String> getForthLevel(String from,Set<String> set){
		Set<String> second = new HashSet<String>();
		//处理第三层所有的站点
		for(String stand:set){
			Set<String> s = new HashSet<String>();
			Map<String, List<Line>> m= new HashMap<String, List<Line>>();
			m.put(stand, this.getLineList(stand, from, s));
			secondLevel.add(m);
			//把第三层可达站点放入set中,供第伍层取用
			second.addAll(s);
		}
		return second;
	}
	
	/**  
	* getSecondLevel: 把上面几个方法融合起来
	* @param from
	* @param set
	* @return 
	* Set<String>  返回类型   
	*/
	private Set<String> getLevelData(String from,Set<String> set,List<Map<String, List<Line>>> Level){
		Set<String> second = new HashSet<String>();
		//处理上一层所有的站点
		for(String stand:set){
			Set<String> s = new HashSet<String>();
			Map<String, List<Line>> m= new HashMap<String, List<Line>>();
			m.put(stand, this.getLineList(stand, from, s));
			Level.add(m);
			//把上一层可达站点放入set中,供下一层取用
			second.addAll(s);
		}
		return second;
	}
	
	
	
	
	/**
	 * getLineList: 获取站点from到可直达节点的所有线路,并把所有可直达节点装入集合中
	 * 
	 * @param fromName
	 * @return List<Line> 返回类型
	 */
	private List<Line> getLineList(String fromName,String from,Set<String> set) {
		// 起始节点在图中的索引
		int fromIndex = MessageInit.TRANSIT_NAME_TO_INDEX.get(fromName.trim());
		List<Line> list = new ArrayList<Line>();
		// 取起始站的所在线路
		Set<StandLineInfo> lines = MessageInit.graph.vexs.get(fromIndex).lines;
		for (StandLineInfo s : lines) {
			// 该站点在线路上的索引
			int index = s.index;
			TransitLine transLine = MessageInit.TRANSIT_LINES.get(s.line.trim());
			if(transLine == null){
				System.out.println(s.line);
			}
			// 处理线路上的每一个站点
			for (int i = 0; i < transLine.lines.length; i++) {
				// 不处理本站点和起始站点
				if (i != index && !from.equals(transLine.lines[i])) {
					Line l = new Line(transLine.lines[i],transLine.lineName, Math.abs(i - index));
					list.add(l);
					set.add(transLine.lines[i]);
				}
			}
		}
		return list;
	}
	/**  
	* getLine: 获取最终线路
	* @param dest
	* @return 
	* List<Line>  返回类型   
	*/
	public List<List<Line>> getLine(String dest){
		List<List<Line>> result = new ArrayList<List<Line>>();
		dealFirstLevel(result, dest);
		dealSecondLevel(result, dest);
		dealThirdLevel(result, dest);
		return result;
		
	}
	/**  
	* dealFirsstLevel:  首先处理不换成的情况
	* void  返回类型   
	*/
	private void dealFirstLevel(List<List<Line>> result,String dest){
		for(Line l:firstLevel){
			if(l.standName.equals(dest)){
				List<Line> temp = new ArrayList<Line>();
				temp.add(l);
				result.add(temp);
			}
			DelRepeat dealRe = new DelRepeat(l.standName,1,l.num,l.lineName);
			isNeedDeal.put(l.standName, dealRe);
		}
	}
	
	/**  
	* dealSecondLevel:  处理换乘一次的情况
	* void  返回类型   
	*/
	private void dealSecondLevel(List<List<Line>> result,String dest){
		for(Map<String, List<Line>> m:secondLevel){
			for(Entry<String, List<Line>> e:m.entrySet()){
				String standName = e.getKey();
				List<Line> l = e.getValue();
				
				//处理二层循环中每一条线路
				for(Line line:l){
					if(line.standName.equals(dest)){
						//如果该站点已经处理过,并且换乘次数和换乘站数都小于当前线路,则不处理当前线路
						if(isNeedDeal.containsKey(line.standName)){
							if((isNeedDeal.get(line.standName)).num == 1 && (isNeedDeal.get(line.standName)).standNum < line.num){
								continue;
							}
						}
						List<List<Line>> firstLine = new ArrayList<List<Line>>();
						this.dealFirstLevel(firstLine, standName);
						//处理当前第二层站点获取到的第一层线路
						for(List<Line> firstLevel:firstLine){
							//最终要加到result里的线路
							List<Line> secondLine = new ArrayList<Line>();
							DelRepeat second = new DelRepeat(line.standName,2,firstLevel.get(0).num + line.num,line.lineName);
							if(firstLevel.get(0).lineName.equals(line.lineName)){
								continue;
							}
							if(isNeedDeal.containsKey(line.standName)){
								if(isNeedDeal.get(line.standName).compareTo(second) == 1){
									continue;
								}else{
									//处理站点
									secondLine.add(firstLevel.get(0));
									secondLine.add(line);
								}
							}else{
								//处理站点
								secondLine.add(firstLevel.get(0));
								secondLine.add(line);
								isNeedDeal.put(line.standName, second);
							}
							if(secondLine.size() != 0){
								if(!hasDoneLine.contains(secondLine)){
									result.add(secondLine);
									hasDoneLine.add(secondLine);
								}
							}
						}
					}
				}
				
			}
		}
	}
	
	/**  
	* dealThirdLevel:  处理换乘两次的情况
	* void  返回类型   
	*/
	private void dealThirdLevel(List<List<Line>> result,String dest){
		for(Map<String, List<Line>> m:thirdLevel){
			for(Entry<String, List<Line>> e:m.entrySet()){
				String standName = e.getKey();
				List<Line> l = e.getValue();
				//处理三层循环中每一条线路
				for(Line line:l){
					if(line.standName.equals(dest)){
						//如果该站点已经处理过,并且换乘次数和换乘站数都小于当前线路,则不处理当前线路
						if(isNeedDeal.containsKey(line.standName)){
							if((isNeedDeal.get(line.standName)).num != 3 && isNeedDeal.get(line.standName).standNum < line.num){
								continue;
							}
						}
						List<List<Line>> secondLevelLine = new ArrayList<List<Line>>();
						this.dealSecondLevel(secondLevelLine, standName);
						//处理当前第二层站点获取到的第一层线路
						for(List<Line> secondLevel:secondLevelLine){
							//最终要加到result里的线路
							List<Line> thirdLine = new ArrayList<Line>();
							DelRepeat third = new DelRepeat(line.standName,3,secondLevel.get(1).num + secondLevel.get(0).num + line.num,line.lineName);
							if(secondLevel.get(1).lineName.equals(line.lineName)){
								continue;
							}
							if(isNeedDeal.containsKey(line.standName)){
								if(isNeedDeal.get(line.standName).compareTo(third) == 1){
									continue;
								}else{
									//处理站点
									thirdLine.add(secondLevel.get(0));
									thirdLine.add(secondLevel.get(1));
									thirdLine.add(line);
								}
							}else{
								//处理站点
								thirdLine.add(secondLevel.get(0));
								thirdLine.add(secondLevel.get(1));
								thirdLine.add(line);
								isNeedDeal.put(line.standName, third);
							}
							if(thirdLine.size() != 0){
								if(!hasDoneLine.contains(thirdLine)){
									result.add(thirdLine);
									hasDoneLine.add(thirdLine);
								}
							}
						}
					}
				}
				
			}
		}
	
	}
	
}

 测试: (还用(四)的参数测,做一下比较)

public static void main(String[] args) {
		// TODO Auto-generated method stub
		long start = System.currentTimeMillis();
		Transit t = new Transit();
		MessageInit.init();
		t.initlevel("西城公交总站");
		List<List<Line>> result = t.getLine("西门");
		int i = 1;
		for(List<Line> l:result){
			System.out.println("第"+ i++ +"条线路,需要换乘"+(l.size() - 1)+"次");
			for(Line line:l){
				System.out.println(line);
			}
		}
		long end = System.currentTimeMillis();
		System.out.println("程序共用了:"+(end - start)+"毫秒");
	}

 结果:

第1条线路,需要换乘0次
乘坐常规公交19路,坐6站西门下车
第2条线路,需要换乘1次
乘坐常规公交19路,坐5站西大岭下车
乘坐常规公交28路,坐1站西门下车
第3条线路,需要换乘1次
乘坐常规公交19路,坐5站西大岭下车
乘坐常规公交11路,坐1站西门下车
第4条线路,需要换乘1次
乘坐常规公交119路,坐3站四季农贸市场下车
乘坐常规公交11路,坐3站西门下车
第5条线路,需要换乘1次
乘坐常规公交119路,坐3站四季农贸市场下车
乘坐常规公交28路,坐3站西门下车
第6条线路,需要换乘2次
乘坐常规公交19路,坐2站海州运管所下车
乘坐常规公交119路,坐1站四季农贸市场下车
乘坐常规公交11路,坐3站西门下车
程序共用了:324毫秒

 可以明显看到,已经没有重复情况了。

测一个比较复杂的参数:从火车站到久和北

结果:

扫描二维码关注公众号,回复: 720262 查看本文章
第1条线路,需要换乘2次
乘坐快速公交(BRT)喂给线1(H1),坐8站龙河广场下车
乘坐常规公交30路,坐28站香缇花园下车
乘坐快速公交(BRT)喂给线6(B15)临时运营线路,坐4站久和北下车
第2条线路,需要换乘2次
乘坐常规公交12路,坐7站龙河广场下车
乘坐常规公交30路,坐28站香缇花园下车
乘坐快速公交(BRT)喂给线6(B15)临时运营线路,坐4站久和北下车
第3条线路,需要换乘2次
乘坐常规公交15路,坐9站振兴大厦下车
乘坐常规公交30路,坐27站香缇花园下车
乘坐快速公交(BRT)喂给线6(B15)临时运营线路,坐4站久和北下车
第4条线路,需要换乘2次
乘坐常规公交夜班线203路,坐9站振兴大厦下车
乘坐常规公交30路,坐27站香缇花园下车
乘坐快速公交(BRT)喂给线6(B15)临时运营线路,坐4站久和北下车
第5条线路,需要换乘2次
乘坐常规公交旅游线路游2路,坐16站新华下车
乘坐常规公交30路,坐19站香缇花园下车
乘坐快速公交(BRT)喂给线6(B15)临时运营线路,坐4站久和北下车
第6条线路,需要换乘2次
乘坐快速公交(BRT)喂给线3(B11),坐17站圣湖路下车
乘坐常规公交30路,坐15站香缇花园下车
乘坐快速公交(BRT)喂给线6(B15)临时运营线路,坐4站久和北下车
第7条线路,需要换乘2次
乘坐常规公交15路,坐9站振兴大厦下车
乘坐常规公交旅游线路游1路,坐15站在海一方下车
乘坐常规公交旅游线路游3路,坐13站久和北下车
第8条线路,需要换乘2次
乘坐常规公交夜班线203路,坐9站振兴大厦下车
乘坐常规公交旅游线路游1路,坐15站在海一方下车
乘坐常规公交旅游线路游3路,坐13站久和北下车
第9条线路,需要换乘2次
乘坐快速公交(BRT)喂给线3(B11),坐21站花果山景区下车
乘坐常规公交旅游线路游1路,坐10站在海一方下车
乘坐常规公交旅游线路游3路,坐13站久和北下车
第10条线路,需要换乘2次
乘坐常规公交旅游线路游2路,坐25站花果山景区下车
乘坐常规公交旅游线路游1路,坐10站在海一方下车
乘坐常规公交旅游线路游3路,坐13站久和北下车
第11条线路,需要换乘2次
乘坐常规公交8路,坐10站苏欣快客站下车
乘坐常规公交旅游线路游1路,坐16站在海一方下车
乘坐常规公交旅游线路游3路,坐13站久和北下车
第12条线路,需要换乘2次
乘坐常规公交22路,坐10站苏欣快客站下车
乘坐常规公交旅游线路游1路,坐16站在海一方下车
乘坐常规公交旅游线路游3路,坐13站久和北下车
第13条线路,需要换乘2次
乘坐常规公交12路,坐11站苍梧小区下车
乘坐常规公交旅游线路游1路,坐14站在海一方下车
乘坐常规公交旅游线路游3路,坐13站久和北下车
第14条线路,需要换乘2次
乘坐常规公交119路,坐4站华北桥下车
乘坐快速公交(BRT)主线B1 ,坐20站院前下车
乘坐常规公交旅游线路游3路,坐7站久和北下车
第15条线路,需要换乘2次
乘坐常规公交11路,坐9站海州客运站下车
乘坐快速公交(BRT)主线B1 ,坐25站院前下车
乘坐常规公交旅游线路游3路,坐7站久和北下车
第16条线路,需要换乘2次
乘坐常规公交12路,坐8站海州客运站下车
乘坐快速公交(BRT)主线B1 ,坐25站院前下车
乘坐常规公交旅游线路游3路,坐7站久和北下车
第17条线路,需要换乘2次
乘坐常规公交4路,坐9站海州客运站下车
乘坐快速公交(BRT)主线B1 ,坐25站院前下车
乘坐常规公交旅游线路游3路,坐7站久和北下车
第18条线路,需要换乘2次
乘坐快速公交(BRT)喂给线1(H1),坐8站龙河广场下车
乘坐快速公交(BRT)主线B1 ,坐15站院前下车
乘坐常规公交旅游线路游3路,坐7站久和北下车
第19条线路,需要换乘2次
乘坐快速公交(BRT)喂给线3(B11),坐14站宋艞下车
乘坐快速公交(BRT)主线B1 ,坐9站院前下车
乘坐常规公交旅游线路游3路,坐7站久和北下车
第20条线路,需要换乘2次
乘坐常规公交12路,坐21站党校下车
乘坐快速公交(BRT)喂给线4(B12),坐24站开发区下车
乘坐常规公交37路,坐5站久和北下车
第21条线路,需要换乘2次
乘坐常规公交11路,坐9站海州客运站下车
乘坐快速公交(BRT)喂给线4(B12),坐49站开发区下车
乘坐常规公交37路,坐5站久和北下车
第22条线路,需要换乘2次
乘坐常规公交4路,坐9站海州客运站下车
乘坐快速公交(BRT)喂给线4(B12),坐49站开发区下车
乘坐常规公交37路,坐5站久和北下车
第23条线路,需要换乘2次
乘坐常规公交旅游线路游2路,坐16站新华下车
乘坐快速公交(BRT)喂给线4(B12),坐23站开发区下车
乘坐常规公交37路,坐5站久和北下车
第24条线路,需要换乘2次
乘坐常规公交15路,坐17站新华下车
乘坐快速公交(BRT)喂给线4(B12),坐23站开发区下车
乘坐常规公交37路,坐5站久和北下车
第25条线路,需要换乘2次
乘坐常规公交夜班线203路,坐17站新华下车
乘坐快速公交(BRT)喂给线4(B12),坐23站开发区下车
乘坐常规公交37路,坐5站久和北下车
第26条线路,需要换乘2次
乘坐常规公交9路,坐13站兴业小区下车
乘坐快速公交(BRT)喂给线4(B12),坐38站开发区下车
乘坐常规公交37路,坐5站久和北下车
第27条线路,需要换乘2次
乘坐快速公交(BRT)喂给线3(B11),坐17站圣湖路下车
乘坐快速公交(BRT)喂给线4(B12),坐19站开发区下车
乘坐常规公交37路,坐5站久和北下车
第28条线路,需要换乘2次
乘坐常规公交17路,坐10站运管处下车
乘坐快速公交(BRT)喂给线4(B12),坐39站开发区下车
乘坐常规公交37路,坐5站久和北下车
第29条线路,需要换乘2次
乘坐常规公交23路,坐16站客运南站下车
乘坐快速公交(BRT)喂给线4(B12),坐33站开发区下车
乘坐常规公交37路,坐5站久和北下车
第30条线路,需要换乘2次
乘坐常规公交119路,坐13站客运南站下车
乘坐快速公交(BRT)喂给线4(B12),坐33站开发区下车
乘坐常规公交37路,坐5站久和北下车
第31条线路,需要换乘2次
乘坐常规公交8路,坐12站客运南站下车
乘坐快速公交(BRT)喂给线4(B12),坐33站开发区下车
乘坐常规公交37路,坐5站久和北下车
第32条线路,需要换乘2次
乘坐常规公交22路,坐12站客运南站下车
乘坐快速公交(BRT)喂给线4(B12),坐33站开发区下车
乘坐常规公交37路,坐5站久和北下车
第33条线路,需要换乘2次
乘坐常规公交23路,坐8站天然居东下车
乘坐常规公交1路,坐13站罗盖特下车
乘坐常规公交37路,坐9站久和北下车
第34条线路,需要换乘2次
乘坐快速公交(BRT)喂给线1(H1),坐8站龙河广场下车
乘坐常规公交1路,坐11站罗盖特下车
乘坐常规公交37路,坐9站久和北下车
第35条线路,需要换乘2次
乘坐常规公交12路,坐7站龙河广场下车
乘坐常规公交1路,坐11站罗盖特下车
乘坐常规公交37路,坐9站久和北下车
第36条线路,需要换乘2次
乘坐常规公交9路,坐10站中茵小区下车
乘坐常规公交1路,坐22站罗盖特下车
乘坐常规公交37路,坐9站久和北下车
第37条线路,需要换乘2次
乘坐常规公交11路,坐13站西门下车
乘坐常规公交1路,坐32站罗盖特下车
乘坐常规公交37路,坐9站久和北下车
第38条线路,需要换乘2次
乘坐常规公交4路,坐13站西门下车
乘坐常规公交1路,坐32站罗盖特下车
乘坐常规公交37路,坐9站久和北下车
第39条线路,需要换乘2次
乘坐常规公交17路,坐10站运管处下车
乘坐常规公交1路,坐20站罗盖特下车
乘坐常规公交37路,坐9站久和北下车
第40条线路,需要换乘2次
乘坐快速公交(BRT)喂给线3(B11),坐5站恒瑞制药下车
乘坐常规公交99路,坐24站德兰国际下车
乘坐快速公交(BRT)喂给线6(B15)临时运营线路,坐2站久和北下车
程序共用了:289毫秒

 对结果进行分析:

H1=>30=>B15
12=>30=>B15
15=>30=>B15
203=>30=>B15
2=>30=>B15
B11=>30=>B15
15=>游1=>游3
203=>游1=>游3
B11=>游1=>游3
游2=>游1=>游3
8=>游1=>游3
22=>游1=>游3
12=>游1=>游3
119=>B1=>游3
11=>B1=>游3
12=>B1=>游3
4=>B1=>游3
H1=>B1=>游3
B11=>B1=>游3
12=>B12=>37
11=>B12=>37
4=>B12=>37
2=>B12=>37
15=>B12=>37
203=>B12=>37
9=>B12=>37
B11=>B12=>37
B12=>B12=>37
23=>B12=>37
119=>B12=>37
8=>B12=>37
12=>B12=>37
23=>1=>37
H1=>1=>37
12=>1=>37
9=>1=>37
11=>1=>37
4=>1=>37
17=>1=>37
B11=>99=>B15

 可以看到,结果中是没有重复数据的。至于哪条线路应该被去掉,那就看具体情况,并且需要更多参数了。

      至此,公交系统暂时告一段落了,以后的测试如果发现什么问题我再回来更新。

猜你喜欢

转载自709002341.iteye.com/blog/2262728