1. 程式人生 > >【圖(上)】圖的遍歷,深度優先,廣度優先

【圖(上)】圖的遍歷,深度優先,廣度優先

深度優先搜尋(Depth First Search, DFS)

類似於樹的先序遍歷
先將根節點設定成已經訪問過,對根節點的每一個鄰接點,選取一個,檢視有沒有訪問過,沒有訪問,設定成訪問,並將此節點作為根結點,重複上述步驟;如果所有鄰接點都已經訪問過,放回到上一步的根節點中,檢視是否有沒有訪問的鄰接點,直到返回到第一步的根節點中。
在這裡插入圖片描述

void DFS(Vertex V)
{
	visited[V] = true;
	for (V 的每個鄰接點W)
		if (!visited[W])
			DFS(W);
}

若有N個頂點、E條邊,時間複雜度是:

  • 用鄰接表儲存圖,有O(N+E)
  • 用鄰接矩陣儲存圖,有O(N2)

廣度優先搜尋(Breadth First Search, BFS)

在這裡插入圖片描述
類似於樹的層序遍歷,先將一個元素壓入佇列之中,設定該元素為已訪問,每次從佇列取出一個元素,並將該元素所有未訪問的鄰接點元素壓入佇列中,直到佇列為空,每次壓入佇列,將該元素設定為已經訪問。

void BFS(Vertex V)
{
	visited[V] = true;
	Enqueue(V, Q);
	while (!IsEmpty(Q))
	{
		V = Dequeue(Q);
		for (V 的每個鄰接點W)
			if (!visited[W])
			{
				visited[
W] = true; Enqueue(W, Q); } } }

若有N個頂點、E條邊,時間複雜度是:

  • 用鄰接表儲存圖,有O(N+E)
  • 用鄰接矩陣儲存圖,有O(N2)

為什麼需要兩種遍歷?
小人從開始的地方找到綠色的出口,白色可以通過,黑色堵住了,可以對角線走,圖中小人出現的地方為訪問過的結點,可以看到不同的搜尋訪問的複雜度時不一樣的。
在這裡插入圖片描述

圖不連通怎麼辦?

  • 連通:如果從V到W存在一條(無向)路徑,則稱V和W是連通的

  • 路徑:V到W的路徑是一系列頂點{V, v1, v2, …,vn, W}的集合,其中任一對相鄰的頂點間都有圖中的邊。路徑的長度

    是路徑中的邊數(如果帶權,則是所有邊的權重和)。如果V到W之間的所有頂點都不同,則稱簡單路徑

  • 迴路:起點等於終點的路徑

  • 連通圖:圖中任意兩頂點均連通

  • 連通分量:無向圖的極大連通子圖

    • 極大頂點數:再加1個頂點就不連通了
    • 極大邊數:包含子圖中所有頂點相連的所有邊
      在這裡插入圖片描述
  • 強連通:有向圖中頂點V和W之間存在雙向路徑,則稱V和W是強連通的

  • 強連通圖:有向圖中任意兩頂點均強連通

  • 強連通分量:有向圖的極大強連通子圖
    在這裡插入圖片描述

void DFS(Vertex V)
{
	visited[V] = true;
	for (V 的每個鄰接點W)
		if (!visited[W])
			DFS(W);
}
void ListComponents(Graph G)
{
	for (each V in G)
		if (!visited[V])
			DFS(V); /*or BFS( V )*/
}