圖的遍歷——廣度優先搜索(Breadth First Search)

1.廣度優先搜索遍歷相似於樹的按層次遍歷的過程。java

假設從圖中某頂點V出發,在訪問了V以後依次訪問V的各個不曾訪問過得鄰接點,而後分別從這些鄰接點出出發,依次訪問他們的鄰接點,並使「先被訪問的頂點的鄰接點」先於「後被訪問的頂點的鄰接點」被訪問。直至圖中全部的已被訪問的頂點的鄰接點都被訪問完。若此時圖中還有未被訪問的頂點,則選一個圖中未被訪問的頂點作起始點,重複上述廣度優先搜索遍歷過程,直到全部的頂點被遍歷完。node

換句話說,廣度優先搜索是以v爲起始點,由近及遠,依次訪問和v路徑相通且路徑長度爲1,2,。。。的頂點。算法

2.如下圖爲例,作個簡單的廣度優先搜索的過程數組

假設以V1頂點爲出發點,首先訪問V1頂點,而後依次訪問V1的鄰接點V2,V3,而後以V1的鄰接點V2,V3爲起始點,分別訪問V2的鄰接點V4,V5,而後訪問V3的鄰接點V6,V7;緊接着分別以V4,V5,V6,V7爲出發點,首先訪問V4的鄰接點V8,訪問V5的鄰接點,V6的鄰接點V9,v7的鄰接點,此時V8,V9的鄰接點都已經被訪問完了,此時圖的遍歷已經結束。code

此時的頂點訪問順序爲:索引

V1->V2->V3->V4->V5->V6->V7->V8->V9隊列

3.和深度優先搜索相似,在遍歷的過程當中也須要一個訪問標誌數組。而且,爲了順次訪問路徑長度爲2,3的頂點,需附設隊列來存儲已 被訪問的路徑長度1,2.。。的頂點;it

4.附上代碼算法:class

example 1: 以隊列爲輔助List

public void BFS1() {
        boolean[] visited = new boolean[mVexs.length];
        for (int i = 0; i < mVexs.length; i++) {
            visited[i] = false;
        }
        Queue<Integer> queue =new LinkedList<>();
        for (int i = 0; i < mVexs.length; i++) {  //遍歷各個頂點
            if (!visited[i]) {
                visited[i] = true;
                System.out.println(i + "(" + mVexs[i].data + ")");
                queue.offer(i);//入隊列,選取一個頂點開始進行廣度優先搜索
            }
            while (queue.isEmpty()) {  //用兩個值來表示隊列,
                //出隊列
                int j=queue.poll();
                ENode node = mVexs[j].firstEdge;
                while (node != null) {
                    if (!visited[node.ivex]) {
                        visited[node.ivex] = true;
                        queue.offer(node.ivex);//入隊列
                        System.out.println(i + "(" + mVexs[node.ivex].data + ")");
                    }
                    node = node.nextEdge;
                }
            }

        }
    }

example2:以數組來實現隊列的輔助 

public void BFS() {
        boolean[] visited = new boolean[mVexs.length];
        for (int i = 0; i < mVexs.length; i++) {
            visited[i] = false;
        }
        int head = 0;
        //用兩個索引的一個int數組來表示輔助隊列,用來存取頂點的位置
        
        int rear = 0;
        int[] queue = new int[mVexs.length];
        for (int i = 0; i < mVexs.length; i++) {  //遍歷各個頂點

            if (!visited[i]) {
                visited[i] = true;
                System.out.println(i + "(" + mVexs[i].data + ")");
                queue[rear++] = i;  //入隊列,選取一個頂點開始進行廣度優先搜索
            }
            while (head != rear) {  //用兩個值來表示隊列,
                int j = queue[head++]; //出隊列
                ENode node = mVexs[j].firstEdge;
                while (node != null) {
                    if (!visited[node.ivex]) {
                        visited[node.ivex] = true;
                        queue[rear++] = node.ivex;  //入隊列
                        System.out.println(i + "(" + mVexs[node.ivex].data + ")");

                    }
                    node = node.nextEdge;
                }
            }

        }
    }

5.時間複雜度

分析上述算法,每一個頂點至多進一次隊列。遍歷圖的過程實質上是經過邊或者弧找鄰接點的過程,所以廣度優先搜索遍歷圖的時間複雜度和深度優先搜索遍歷相同。二者不一樣的地方僅在於對頂點訪問時間的順序不一樣。

相關文章
相關標籤/搜索