Java实现深度优先遍历-DFS

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.实现效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值