java數據結構與算法總結(七)--【圖數據結構的遍歷】java實現廣度優先和深度優先遍歷

來自

寬度優先搜索(BFS)遍歷圖需要使用隊列queue數據結構; 深度優先搜索(DFS, Depth First Search)的實現
需要使用到棧stack數據結構。

java中雖然有Queue接口,單java並沒有給出具體的隊列實現類,而Java中讓LinkedList類實現了Queue接口,所以使用隊列的時候,一般採用LinkedList。因爲LinkedList是雙向鏈表,可以很方便的實現隊列的所有功能。
java中定義隊列 一般這樣定義: Queue queue = new LinkedList();

java中的棧由java.util.Stack類實現,是一個後進先出(last in first out,LIFO)的堆棧,在Vector類的基礎上擴展5個方法而來。

E push(E item)   
         把項壓入堆棧頂部。   
E pop()   
         移除堆棧頂部的對象,並作爲此函數的值返回該對象。   
E peek()   
         查看堆棧頂部的對象,但不從堆棧中移除它。   
boolean empty()   
         測試堆棧是否爲空。    
int search(Object o)   
         返回對象在堆棧中的位置,以 1 爲基數。

 BFS和DFS遍歷代碼實現如下:

import java.util.*;

/**
 * 使用java實現圖的圖的廣度優先 和深度優先遍歷算法。
 */
public class GraphLoopTest {
    private Map<String, List<String>> graph = new HashMap<String, List<String>>();

    /**
     * 初始化圖數據:使用鄰居表來表示圖數據。
     */
    public void initGraphData() {
//        圖結構如下
//          1
//        /   \
//       2     3
//      / \   / \
//     4  5  6  7
//      \ | / \ /
//        8    9
        graph.put("1", Arrays.asList("2", "3"));
        graph.put("2", Arrays.asList("1", "4", "5"));
        graph.put("3", Arrays.asList("1", "6", "7"));
        graph.put("4", Arrays.asList("2", "8"));
        graph.put("5", Arrays.asList("2", "8"));
        graph.put("6", Arrays.asList("3", "8", "9"));
        graph.put("7", Arrays.asList("3", "9"));
        graph.put("8", Arrays.asList("4", "5", "6"));
        graph.put("9", Arrays.asList("6", "7"));
    }

    /**
     * 寬度優先搜索(BFS, Breadth First Search)
     * BFS使用隊列(queue)來實施算法過程
     */
    private Queue<String> queue = new LinkedList<String>();
    private Map<String, Boolean> status = new HashMap<String, Boolean>();

    /**
     * 開始點
     *
     * @param startPoint
     */
    public void BFSSearch(String startPoint) {
        //1.把起始點放入queue;
        queue.add(startPoint);
        status.put(startPoint, false);
        bfsLoop();
    }

    private void bfsLoop() {
        //  1) 從queue中取出隊列頭的點;更新狀態爲已經遍歷。
        String currentQueueHeader = queue.poll(); //出隊
        status.put(currentQueueHeader, true);
        System.out.println(currentQueueHeader);
        //  2) 找出與此點鄰接的且尚未遍歷的點,進行標記,然後全部放入queue中。
        List<String> neighborPoints = graph.get(currentQueueHeader);
        for (String poinit : neighborPoints) {
            if (!status.getOrDefault(poinit, false)) { //未被遍歷
                if (queue.contains(poinit)) continue;
                queue.add(poinit);
                status.put(poinit, false);
            }
        }
        if (!queue.isEmpty()) {  //如果隊列不爲空繼續遍歷
            bfsLoop();
        }
    }


    /**
     * 深度優先搜索(DFS, Depth First Search)
     * DFS使用隊列(queue)來實施算法過程
     * stack具有後進先出LIFO(Last Input First Output)的特性,DFS的操作步驟如下:
     */
//     1、把起始點放入stack;
//     2、重複下述3步驟,直到stack爲空爲止:
//    從stack中訪問棧頂的點;
//    找出與此點鄰接的且尚未遍歷的點,進行標記,然後全部放入stack中;
//    如果此點沒有尚未遍歷的鄰接點,則將此點從stack中彈出。

    private Stack<String> stack = new Stack<String>();
    public void DFSSearch(String startPoint) {
        stack.push(startPoint);
        status.put(startPoint, true);
        dfsLoop();
    }

    private void dfsLoop() {
        if(stack.empty()){
            return;
        }
        //查看棧頂元素,但並不出棧
        String stackTopPoint = stack.peek();
        //  2) 找出與此點鄰接的且尚未遍歷的點,進行標記,然後全部放入queue中。
        List<String> neighborPoints = graph.get(stackTopPoint);
        for (String point : neighborPoints) {
            if (!status.getOrDefault(point, false)) { //未被遍歷
                stack.push(point);
                status.put(point, true);
                dfsLoop();
            }
        }
        String popPoint =  stack.pop();
        System.out.println(popPoint);
    }

    public static void main(String[] args) {
        GraphLoopTest test = new GraphLoopTest();
        test.initGraphData();
//        test.BFSSearch("1");
        test.DFSSearch("1");
    }
}

 

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