圖的遍歷之DFS與BFS

圖的遍歷

圖的遍歷指的是從圖中的任一頂點出發,對圖中的所有頂點訪問一次且只訪問一次。圖的遍歷操作和樹的遍歷操作功能相似。圖的遍歷是圖的一種基本操作,圖的許多其它操作都是建立在遍歷操作的基礎之上。
根據訪問節點的順序,我們可以分成兩種方法來對圖進行遍歷。分別是深度優先遍歷(DFS)廣度優先遍歷(BFS)

DFS

算法思想:

從某個點一直往深處走,走到不能往下走之後,就回退到上一步,直到找到解或把所有點走完。

算法步驟(遞歸或棧實現)
  1. 訪問指定起始地點。
  2. 若當前訪問頂點的鄰接頂點有未被訪問的頂點,就任選一個訪問。如果沒有就回退到最近訪問的頂點,直到與起始頂點相通的所有點被遍歷完。
  3. 若途中還有頂點未被訪問,則再選一個點作爲起始頂點。重複步驟2(針對非連通圖)。
算法實現
import java.util.Stack;

public class Demo_01_DFS {
    //遞歸版DFS
    public static void DFSbyRecursion(int[][] graph){
        int length = graph.length;
        boolean[] visited = new boolean[length];
        //爲了預防圖不是連通圖的情況,若圖爲連通圖則直接調用DFS,不需要for循環
        for (int i = 0; i < length; i++) {
            if(!visited[i])
                DFS(graph,i,visited);
        }
    }

    public static void DFS(int[][] graph,int vertex,boolean[] visited){
        visited[vertex] = true;
        //遍歷該點
        System.out.print(vertex + " ");
        int length = graph.length;
        for (int i = 0; i < length; i++) {
            //找出與vertex相鄰的點,進行DFS。找到一個點就DFS,遍歷到底了就進行回退(這裏注意遞歸的過程,)
            if(!visited[i] && graph[vertex][i] == 1){
                DFS(graph,i,visited);
            }
        }
    }

    //用棧實現DFS
    public static void DFSbyStack(int[][] graph){
        Stack<Integer> stack = new Stack<>();
        int length = graph.length;
        //判斷元素是否被遍歷過
        boolean[] visited = new boolean[length];
        for (int i = 0; i < length; i++) {
            if(!visited[i]){
                stack.push(i);
                visited[i] = true;
                boolean hasNext;
                //遍歷第一個點
                System.out.print( i+ " ");
                while(!stack.empty()){
                    //取出棧頂元素
                    int temp = stack.peek();
                    //設置變量來判斷是否有新點入棧,沒有就彈出棧頂元素,有的話進行下一次循環。
                    hasNext = false;
                    for (int j = 0; j < length; j++) {
                        //找出一個與棧頂元素有連接且沒有被遍歷的點放入stack中,並遍歷該點
                        if(!visited[j] && graph[temp][j] == 1){
                            stack.push(j);
                            visited[j] = true;
                            hasNext = true;
                            //遍歷該點
                            System.out.print(j + " ");
                            break;
                        }
                    }
                    //如果沒有下一個元素則回溯,刪除棧頂元素
                    if (!hasNext){
                        stack.pop();
                    }
                }
            }
        }

    }
    public static void main(String[] args) {
        int[][] graph = {
                { 0, 1, 1, 0, 0 },
                { 0, 0, 1, 0, 1 },
                { 0, 0, 0, 0, 0 },
                { 1, 1, 0, 0, 1 },
                { 0, 0, 1, 0, 0 }
        };
        DFSbyRecursion(graph);
        System.out.println();
        DFSbyStack(graph);
    }
}

BFS

算法思想

從某個點一直把其鄰接點走完,然後任選一個鄰接點把與之鄰接的未被遍歷的點走完,如此反覆走完所有結點。類似於樹的層序遍歷。

算法步驟(用隊列實現)
  1. 訪問指定起始點。
  2. 訪問當前頂點的鄰接頂點有未被訪問的頂點,並將之放入隊列中。
  3. 刪除隊列的隊首節點。訪問當前隊列的隊首,重複步驟2。直到隊列爲空。
  4. 若若途中還有頂點未被訪問,則再選一個點作爲起始頂點。重複步驟2。(針對非連通圖)。
算法實現
import java.util.LinkedList;
import java.util.Queue;

public class Demo_02_BFS {
    //用隊列來實現BFS
    public static void BFSbyQueue(int[][] graph){
        Queue<Integer> queue = new LinkedList<>();
        int length = graph.length;
        boolean[] visited = new boolean[length];

        //爲了預防圖不是連通圖的情況,若圖爲連通圖則不需要for循環
        for (int i = 0; i < length; i++) {
            if(!visited[i]){
                queue.add(i);
                visited[i] = true;
                System.out.print(i + " ");
                while(queue.size() != 0){
                    int temp = queue.poll();
                    //遍歷所有與temp相鄰的點,依次加入隊列中,並遍歷他們
                    for (int j = 0; j < length; j++) {
                        if(!visited[j] && graph[temp][j] == 1){
                            queue.add(j);
                            visited[j] = true;
                            System.out.print(j + " ");
                        }
                    }
                }//while
            }
        }
    }

    public static void main(String[] args) {
        int[][] graph = {
                { 0, 1, 0, 1, 0 },
                { 0, 0, 1, 0, 1 },
                { 0, 0, 0, 0, 0 },
                { 1, 1, 0, 0, 1 },
                { 0, 0, 1, 0, 0 }
        };
        BFSbyQueue(graph);
    }
}

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