廣度優先遍歷
基礎概念及圖解
概念:
廣度優先遍歷算法是圖的另一種基本遍歷算法,其基本思想是盡最大程度輻射能夠覆蓋的節點,並對其進行訪問。
以迷宮為例,廣度優先搜索則可以想象成一組人一起朝不同的方向走迷宮,當出現新的未走過的路的時候,可以理解成一個人有分身術,繼續從不同的方向走,,當相遇的時候則是合二為一
自我理解:
正如老師上課所說的,廣度優先遍歷就像在平靜的湖面丟入一塊石頭,盪起的波紋,從離起始點最近的先開始遍歷,同樣距離的前后順序可以交換,如果有環狀結構,那遍歷過的,就可以跳過,不用重復遍歷。
例子解析
例子1:

1.從起點0開始遍歷

2.從其鄰接表得到所有的鄰接節點,把這三個節點都進行標記,表示已經訪問過了

3.從0的鄰接表的第一個頂點2開始尋找新的叉路

4.查詢頂點2的鄰接表,並將其所有的鄰接節點都標記為已訪問

5.繼續從頂點0的鄰接表的第二個節點,也就是頂點1,遍歷從頂點1開始

6.查詢頂點1的鄰接表的所有鄰接節點,也就是頂點0和頂點2,發現這兩個頂點都被訪問過了,頂點1返回

7.從頂點0的下一個鄰接節點,也就是頂點5,開始遍歷

8.查詢頂點5的鄰接節點,發現其鄰接節點3和0都被訪問過了,頂點5返回

9.繼續從2的下一個鄰接節點3開始遍歷

10.尋找頂點3的鄰接節點,發現都被訪問過了,頂點3返回

11.繼續尋找頂點2的下一個鄰接節點4,發現4的所有鄰接節點都被訪問過了,頂點4返回

12.頂點2的所有鄰接節點都放過了,頂點2返回,遍歷結束

例子二
-
對下圖連通無向圖廣度優先搜索(以v0為出發點):v0,v1,v2,v3,v4,v5,v6,v7,v8

-
對下圖非連通無向圖廣度優先搜索(以v0為出發點):v0,v1,v2,v3,v4,v5,v6,v7,v4為另一個起始點


-
對下圖有向圖的廣度優先搜索(v2為出發點):v2,v1,v3,v0,v4

-
對下圖有向圖的廣度優先搜索(v0為出發點):v0,v1,v4,v3,v2,v2為另一出發點

算法實現
private Iterator<T> iteratorBFS(int startIndex) {
Integer x;//定義一個int型數字
QueueADT<Integer> traversalQueue = new LinkedQueue<Integer>();//定義一個隊列
UnorderedListADT<T> resultList = new ArrayUnorderedList<T>();//定義一個數組(該數組保存最后的遍歷后順序)
//索引無效,返回空。即如果索引值不在數組索引值范圍內,返回空。
if (!indexIsValid(startIndex))
return resultList.iterator();
boolean[] visited = new boolean[maxCount];//新建一個Boolean型數組,大小和上面數組一樣
//把所有頂點設為false,白色
for (int i = 0; i < maxCount; i++)
visited[i] = false;
//進入隊列的為true,即訪問過的,灰色
traversalQueue.enqueue(startIndex);//先將起始結點加入隊列中
visited[startIndex] = true;//並將該結點在Boolean型數組中由false改為ture,表示已經被遍歷過。
while (!traversalQueue.isEmpty()) //如果隊列不為空
{
//出隊列塗黑存入resultList中
x = traversalQueue.dequeue();//將隊列里的數取出
resultList.addToRear((T) nodelist.get(x).getElement());//並將其存入數組里
//如果進入resultList的頂點還有相鄰的未訪問過的頂點,將其塗灰入隊
for (int i = 0; i < maxCount; i++)
{
if (hasEdge(x, i) && !visited[i]) //如果進入resultList的頂點還有相鄰的未訪問過的頂點
{
traversalQueue.enqueue(i);//將其加入隊列
visited[i] = true;//標為已經遍歷過
Int++;
}
}
}
return new GraphIterator(resultList.iterator());
}
