Java实现深度优先遍历-DFS
实现功能:使用深度优先遍历算法DFS计算地铁指定起点站和终点站之间的所有路径
1.构造地铁站点数据结构
地铁站点数据结构包含2个属性,1个站点名,1个邻接站点列表
import java.util.LinkedList;
import java.util.List;
public class StationNode {
private String stationName; // 站点名称
private List <StationNode> neighborStationList; //邻接站点list
public StationNode(String stationName) {
this.stationName = stationName;
this.neighborStationList = new LinkedList<>();
}
public String getStationName() {
return stationName;
}
public void setStationName(String stationName) {
this.stationName = stationName;
}
public List<StationNode> getNeighborStationList() {
return neighborStationList;
}
public void setNeighborStationList(List<StationNode> neighborStationList) {
this.neighborStationList = neighborStationList;
}
// 判断node站点是否在邻接站点列表中
public boolean nodeIsExistInList(StationNode node) {
for(StationNode stationNode: neighborStationList) {
if(stationNode.getStationName().equals(node.getStationName()))
return true;
}
return false;
}
}
2.深度优先遍历核心算法类
输入:所有的地铁站点Map-nodeMap,起点站名称-startStationName,终点站名称-endStationName
输出:起点站到终点站之间的所有路径
初始化 DFSCacul 算法类
-
所有地铁站点Map-nodeMap
-
未搜索的站点Map-notSearchMap
-
已搜索的站点Map-isSearchMap
-
起点站名称-startStationName
-
终点站名称-endStationName
-
遍历路径Map-pathMap
-
栈结构List-nodeStack
初始化DFS计算
- 将起点对应的地铁站点对象入栈
- 调用 DFS 方法进行计算
DFS核心算法部分
伪代码
DFS() {
if( 未遍历站点不为空 )
if( 栈结构List不为空 )
当前遍历地铁站点,stationNode = nodeStack 出栈元素
从未遍历站点Map移除该站点,
将该站点加入已遍历站点Map
获得该站点的邻接站点列表 neighborStationList
for遍历邻接站点列表
if( 邻接站点在未搜索的站点Map中 )
遍历路径Map放入,key--邻接站点名key,value--当前遍历地铁站点stationNode
if( 邻接站点名 == 终点站名 )
打印路径
else
邻接站点入栈
DFS
else
从未遍历站点Map中随机取一个站点入栈;
DFS();
else
算法结束;
}
完整代码
import java.util.*;
public class DFSCacul {
private Map<String, StationNode> nodeMap; // 初始站点Map
private Map<String, StationNode> notSearchMap; // 未搜索站点Map
private Map<String, StationNode> isSearchMap; // 已搜索站点Map
private Map<String, StationNode> pathMap; // 遍历路径Map
private LinkedList <StationNode> nodeStack; // 遍历节点栈
private String startStationName; // 开始站点名称
private String endStationName; // 终结站点名称
public DFSCacul(Map<String, StationNode> map, String startStationName, String endStationName) {
this.nodeMap = map;
this.notSearchMap = map;
this.isSearchMap = new HashMap<>();
this.startStationName = startStationName;
this.endStationName = endStationName;
this.pathMap = new HashMap<>();
this.nodeStack = new LinkedList<>();
}
public Map<String, StationNode> getPathMap() {
return pathMap;
}
public void setPathMap(Map<String, StationNode> pathMap) {
this.pathMap = pathMap;
}
//深度优先遍历初始化
public void cacul() {
System.out.println();
System.out.println("遍历开始--");
System.out.println("notSearchMap--" + notSearchMap.size());
System.out.println("isSearchMap--" + isSearchMap.size());
System.out.println();
StationNode node = nodeMap.get(startStationName);
nodeStack.addLast(node);
DFS();
System.out.println();
System.out.println("遍历结束--");
System.out.println("notSearchMap--" + notSearchMap.size());
System.out.println("isSearchMap--" + isSearchMap.size());
System.out.println();
}
public void DFS() {
if(notSearchMap.size() != 0) {
if(nodeStack.size() != 0) {
StationNode stationNode = nodeStack.removeLast(); // 获取栈顶元素
String stationName = stationNode.getStationName();
isSearchMap.put(stationName,stationNode); // 将站点放入已遍历集合
notSearchMap.remove(stationName); // 从站点集合中移除元素
List<StationNode> neighborStationList = stationNode.getNeighborStationList(); // 获取出栈节点的邻接站点列表
for(int i = 0; i < neighborStationList.size(); i++) { // 从该节点的邻接节点列表中选取未被遍历的节点放入栈中
StationNode node = neighborStationList.get(i);
if(notSearchMap.containsKey(node.getStationName())) {
node = nodeMap.get(node.getStationName());
this.pathMap.put(node.getStationName(), stationNode);
if(node.getStationName().equals(endStationName)) { // 邻接顶点包括终结节点,打印路径,继续遍历
printPath();
} else {
nodeStack.addLast(node);
}
}
}
DFS();
} else {
nodeStack.addLast(getRandStationNode()); // 当前栈为空时,从未被遍历的站点中随机选取元素入栈
DFS();
}
}
}
// 从未被遍历的Map中随机获取一个站点
public StationNode getRandStationNode() {
StationNode stationNode = null;
int rand = new Random().nextInt(this.notSearchMap.size());
int i = 0;
for(String stationName : this.notSearchMap.keySet()) {
if(i == rand) {
System.out.println("随机选取站--" + stationName);
stationNode = nodeMap.get(stationName);
}
i ++;
}
return stationNode;
}
public void printPath() {
LinkedList<StationNode> stationList = new LinkedList<>();
String stationName = endStationName;
stationList.addLast(nodeMap.get(endStationName));
while(!stationName.equals(startStationName)) {
stationList.addFirst(pathMap.get(stationName));
stationName = pathMap.get(stationName).getStationName();
}
System.out.println();
System.out.println("获得一条遍历路径————");
for(int i = 0; i < stationList.size(); i++) {
StationNode stationNode = stationList.get(i);
System.out.println(stationNode.getStationName());
}
System.out.println();
}
}
3.数据初始化及测试
测试类
import java.util.HashMap;
import java.util.Map;
/**
* 深度优先遍历计算所有地铁线路
* 此处使用南京地铁部分线路进行测试
*/
public class DFSMain {
// line1 = "1号线";
private static final String line1Station = "迈皋桥站-红山动物园站-南京站-新模范马路站-玄武门站-鼓楼站-" +
"珠江路站-新街口站-张府园站-三山街站-中华门站-安德门站-天隆寺站-软件大道站-" +
"花神庙站-南京南站-双龙大道站-河定桥站-胜太路站-百家湖站-小龙湾站-竹山路站-天印大道站-" +
"龙眠大道站-南医大·江苏经贸学院站-南京交院站-中国药科大学站";
// line2 = "2号线";
private static final String line2Station = "油坊桥站-雨润大街站-元通站-奥体东站-兴隆大街站-集庆门大街站-云锦路站-莫愁湖站-" +
"汉中门站-上海路站-新街口站-大行宫站-西安门站-明故宫站-苜蓿园站-下马坊站-孝陵卫站-钟灵街站-马群站-金马路站-" +
"仙鹤门站-学则路站-仙林中心站-羊山公园站-南大仙林校区站-经天路站";
// line3 = "3号线";
private static final String line3Station = "林场站-星火路站-东大成贤学院站-泰冯路站-天润城站-柳州东路站-上元门站-五塘广场站-" +
"小市站-南京站-新庄站-鸡鸣寺站-浮桥站-大行宫站-常府街站-夫子庙站-武定门站-雨花门站-卡子门站-大明路站-明发广场站-南京南站-" +
"宏运大道站-胜太西路站-天元西路-九龙湖站-诚信大道站-东大九龙湖校区站-秣周东路站";
// line4 = "4号线";
private static final String line4Station = "龙江站-草场门站-云南路站-鼓楼站-鸡鸣寺站-九华山站-岗子村站-蒋王庙站-王家湾站-聚宝山站-" +
"徐庄站-金马路站-汇通路站-灵山站-东流站-孟北站-桦墅站-仙林湖站";
// line10 = "10号线";
private static final String line10Station = "雨山路站-文德路站-龙华路站-南京工业大学站-浦口万汇城站-临江.青奥体育公园站-江心洲站-" +
"绿博园站-梦都大街站-奥体中心站-元通站-中胜站-小行站-安德门站";
public static void main(String [] args) {
Map<String, StationNode> map = new HashMap<>();
InitData.initStation(map,line1Station);
InitData.initStation(map,line2Station);
InitData.initStation(map,line3Station);
InitData.initStation(map,line4Station);
InitData.initStation(map,line10Station);
DFSCacul cacuPath = new DFSCacul(map,"油坊桥站","新街口站");
cacuPath.cacul();
}
}
数据初始化类
import java.util.HashMap;
import java.util.Map;
/**
* 深度优先遍历计算所有地铁线路
* 此处使用南京地铁部分线路进行测试
*/
public class DFSMain {
private static final String line1 = "1号线";
private static final String line2 = "2号线";
private static final String line3 = "3号线";
private static final String line4 = "4号线";
private static final String line10 = "10号线";
private static final String line1Station = "迈皋桥站-红山动物园站-南京站-新模范马路站-玄武门站-鼓楼站-" +
"珠江路站-新街口站-张府园站-三山街站-中华门站-安德门站-天隆寺站-软件大道站-" +
"花神庙站-南京南站-双龙大道站-河定桥站-胜太路站-百家湖站-小龙湾站-竹山路站-天印大道站-" +
"龙眠大道站-南医大·江苏经贸学院站-南京交院站-中国药科大学站";
private static final String line2Station = "油坊桥站-雨润大街站-元通站-奥体东站-兴隆大街站-集庆门大街站-云锦路站-莫愁湖站-" +
"汉中门站-上海路站-新街口站-大行宫站-西安门站-明故宫站-苜蓿园站-下马坊站-孝陵卫站-钟灵街站-马群站-金马路站-" +
"仙鹤门站-学则路站-仙林中心站-羊山公园站-南大仙林校区站-经天路站";
private static final String line3Station = "林场站-星火路站-东大成贤学院站-泰冯路站-天润城站-柳州东路站-上元门站-五塘广场站-" +
"小市站-南京站-新庄站-鸡鸣寺站-浮桥站-大行宫站-常府街站-夫子庙站-武定门站-雨花门站-卡子门站-大明路站-明发广场站-南京南站-" +
"宏运大道站-胜太西路站-天元西路-九龙湖站-诚信大道站-东大九龙湖校区站-秣周东路站";
private static final String line4Station = "龙江站-草场门站-云南路站-鼓楼站-鸡鸣寺站-九华山站-岗子村站-蒋王庙站-王家湾站-聚宝山站-" +
"徐庄站-金马路站-汇通路站-灵山站-东流站-孟北站-桦墅站-仙林湖站";
private static final String line10Station = "雨山路站-文德路站-龙华路站-南京工业大学站-浦口万汇城站-临江.青奥体育公园站-江心洲站-" +
"绿博园站-梦都大街站-奥体中心站-元通站-中胜站-小行站-安德门站";
public static void main(String [] args) {
Map<String, StationNode> map = new HashMap<>();
InitData.initStation(map,line1Station);
InitData.initStation(map,line2Station);
InitData.initStation(map,line3Station);
InitData.initStation(map,line4Station);
InitData.initStation(map,line10Station);
DFSCacul cacuPath = new DFSCacul(map,"油坊桥站","新街口站");
cacuPath.cacul();
}
}
4.实现效果