安琪拉教魯班學算法之BFS和DFS

安琪拉教魯班學算法之BFS和DFS

《安琪拉與面試官二三事》系列文章
一個HashMap能跟面試官扯上半個小時
一個synchronized跟面試官扯了半個小時

《安琪拉教魯班學算法》系列文章

安琪拉教魯班學算法之動態規劃

安琪拉教魯班學算法之BFS和DFS

BFS 和 DFS在算法中屬於有舉足輕重的地位,本文希望通過使用王者峽谷二位脆皮英雄對話的方式講解動態規劃,讓大家在輕鬆愉快的氛圍中搞懂BFS 和 DFS。

魯班: 安琪拉,你知道 BFS 和DFS 嗎?

安琪拉:當然知道啊,BFS 全程是 廣度優先搜索, DFS 指的是深度優先搜索。

魯班: 安琪拉妹妹,你這麼說我還是很蒙,能跟我詳細講講嗎?

安琪拉:魯班哥哥,看你求知慾這麼強,咱倆又都是脆皮的份上,我給你講講BFS 和 DFS。

以下圖爲例,

image-20200405224937276

廣度優先搜索 和 深度優先搜索都是遍歷圖/樹 節點的方式

廣度優先搜索: 如下圖所示,廣度優先搜索,例如從上圖中選取一個節點A,作爲起點,寬度優先搜索,遍歷的方式是遍歷A、 和A相連的B和C,和B相連的D,和C相連的E,和D相連的F,以這樣的順序訪問圖中的節點。

image-20200405230451524

深度優先搜索:還是以A作爲起點,一直走到底,直到不能訪問,再回退,A => B => D => F =>E => C

image-20200405230717269

代碼實現例子:

public static void main(String[] args) {
				//以map 存儲圖中節點的關係 A 相連的節點爲 B、C
  	    //就可表示爲 List<Character> aList = new LinkedList<>(Arrays.asList('B','C'));
        Map<Character, List<Character>> graph = buildGraph();

        dfs(graph, 'A');

        bfs(graph, 'A');
    }

		// 構造圖
    private static Map<Character,List<Character>> buildGraph(){
        Map<Character, List<Character>> graph = new HashMap<>();
        List<Character> aList = new LinkedList<>(Arrays.asList('B','C'));
        List<Character> bList = new LinkedList<>(Arrays.asList('A','C','D'));
        List<Character> cList = new LinkedList<>(Arrays.asList('A','B','D','E'));
        List<Character> dList = new LinkedList<>(Arrays.asList('B','F','E','C'));
        List<Character> eList = new LinkedList<>(Arrays.asList('C','D'));
        List<Character> fList = new LinkedList<>(Arrays.asList('D'));
        graph.put('A',aList);
        graph.put('B',bList);
        graph.put('C',cList);
        graph.put('D',dList);
        graph.put('E',eList);
        graph.put('F',fList);
        return graph;
    }

    /**
     * 深度優先搜索  關鍵是使用棧來維護相鄰後繼節點
     * @param graph 要遍歷的圖
     * @param s 起始點
     */
    public static void dfs(Map<Character,List<Character>> graph, Character s){
        //走過的節點
        Set<Character> visited = new HashSet<>();
        Stack<Character> stack = new Stack<>();
        stack.push(s);

        while(!stack.empty()){
            Character accessC = stack.pop();
            if(!visited.contains(accessC)){
                //訪問函數
                System.out.print("->"+accessC);
                visited.add(accessC);
            }
            graph.get(accessC).forEach(c ->{
                if(!visited.contains(c)){
                    stack.push(c);
                }
            });
        }
    }

    /**
     * 廣度優先搜索  使用隊列維護相鄰後續節點
     * @param graph
     * @param s
     */
    public static void bfs(Map<Character,List<Character>> graph, Character s){
        //走過的節點
        Set<Character> visited = new HashSet<>();
        Queue<Character> queue = new LinkedList<>();

        queue.offer(s);

        while (!queue.isEmpty()){
            Character accessC = queue.poll();
            if(!visited.contains(accessC)){
                //訪問函數
                System.out.print("->"+accessC);
                visited.add(accessC);
            }
            graph.get(accessC).forEach(c ->{
                if(!visited.contains(c)){
                    queue.offer(c);
                }
            });
        }
    }

歡迎大家關注 Wx公衆號:安琪拉的博客 獲取更多技術資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章