數據結構與算法之圖的深度遍歷

學習圖的遍歷之前得知道圖的表示方法
可以參考
圖的表示方法

進入正題
什麼是圖的深度遍歷算法
所謂深度遍歷 就是一口氣一條路走到底,再回溯重複便可達到遍歷效果
一組圖片來說明這個問題
深度遍歷這個圖

圖

第一步
這裏寫圖片描述

第二步
這裏寫圖片描述

依次遍歷直到到最底部

這裏寫圖片描述

到達底部後 回溯重複 也就是回溯到C
然後,C開始訪問未訪問的邊,也是訪問到底部

這裏寫圖片描述

F回溯到E E開始訪問未訪問的邊

這裏寫圖片描述

D回溯 到 E E開始訪問未訪問的邊

這裏寫圖片描述

到此所有的節點已經訪問完成 但是程序並未停止直到回溯至A點(遞歸的特性)

上面的圖片非常清楚的描述了深度遍歷的過程
接下來我將用Java實現這個算法
水平有限 若有錯誤 歡迎指正

//這裏使用的是鄰接矩陣方法
public class DFS {
    GraphByMatrix graphByMatrix = new GraphByMatrix(10);
    Stack<Node> stack;
    List<Node> list;

    class Node {
        // 節點數據
        String str;
        boolean visited;
        // 該節點對應在關係矩陣中的編號
        int numner;

        public Node(String str, int num) {
            this.str = str;
            this.numner = num;
        }
    }

    public DFS() {
        stack = new Stack<>();
        list = new ArrayList<Node>();
        for (int i = 0; i < 8; i++) {
            // 節點內容分別爲A-H 對應編號0-7
            list.add(new Node(new String(Character.toChars('A' + i)), i));
        }
    }

    public void Dfs() {
        // 被訪問過
        list.get(7).visited = true;
        System.out.print(list.get(7).str + "  ");
        // 被訪問過後壓入棧
        stack.push(list.get(7));
        // 棧不爲空則沒有遍歷完全
        while (!stack.isEmpty()) {
            // 返回棧頂元素
            Node peek = stack.peek();
            int nextVertex = getNextVertex(peek);
            // 沒找到 證明所有邊都已經遍歷
            if (nextVertex == -1) {
                // 刪除這個頂點
                stack.pop();
                // 找到了 將這個點作爲下一次的頂點
            } else {
                list.get(nextVertex).visited = true;
                System.out.print(list.get(nextVertex).str + "  ");
                stack.push(list.get(nextVertex));
            }
        }
    }

    // 遞歸
    public void DFs(int index, List<Node> list) {
        //訪問到底部或者該節點沒有未訪問的邊
        if (index == -1)
            return;
        Node node = list.get(index);
        node.visited = true;
        System.out.print(node.str + " ");
        while (getNextVertex(node) != -1)
            DFs(getNextVertex(node), list);
    }
    //獲取與Node 相連的未訪問的邊
    public int getNextVertex(Node peek) {
        boolean[][] matrix = graphByMatrix.matrix;
        for (int i = 0; i < matrix.length; i++) {
            // 查找頂點沒有訪問過的節點
            if (matrix[peek.numner][i] == true && list.get(i).visited == false) {
                return i;
            }
        }
        return -1;
    }

    //建立圖 用來測試的
    public void bulid() {
        //描述關係 這裏是雙向邊 所以 A B 相連後不需要 B A相連會自動連上
        //A B 相連
        graphByMatrix.addEdge(0, 1);
        //B C 相連 
        graphByMatrix.addEdge(1, 2);
        //B D 相連
        graphByMatrix.addEdge(1, 3);
        //C G 相連
        graphByMatrix.addEdge(2, 6);
        // C E 相連
        graphByMatrix.addEdge(2, 4);
        // D E 相連 
        graphByMatrix.addEdge(3, 4);
        // E F 相連
        graphByMatrix.addEdge(4, 5);
        // E H 相連
        graphByMatrix.addEdge(4, 7);
    }
}

測試代碼

    public static void main(String[] args) {
        DFS dfs = new DFS();
        dfs.bulid();
        dfs.Dfs(0);
    }

結果
A  E  C  B  D  G  F  H 

發現和上面推理的順序不一樣原因在於矩陣法的構建
節點會找矩陣中離他近的邊 

圖片只是描述深度遍歷的過程,當一個節點有多條未訪問的邊,選擇的不同,會導致結果的不一樣。

到此深度遍歷差不多結束了。

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