(二) 圖的遍歷
1. 深度優先搜索 (Depth First Search, DFS)
[外鏈圖片轉存失敗(img-MgjNKZTh-1567356455556)(C:\Users\alway\AppData\Roaming\Typora\typora-user-images\1567347155834.png)]
void DFS(Vertex v) {
visited[v] = true;
for (v的每個鄰接點w) {
if(!visited[w]) {
DFS(w);
}
}
}
**注:**可用stack改遞歸爲循環
**時間複雜度:**若有N個頂點,E條邊
-
用鄰接表存儲圖,
-
用鄰接矩陣存儲圖,
2. 廣度優先搜索 (Breadth First Search, BFS)
[外鏈圖片轉存失敗(img-IjMMPRMt-1567356455557)(C:\Users\alway\AppData\Roaming\Typora\typora-user-images\1567347826519.png)]
void BFS(Vertex v) {
visited[v] = true;
Enqueue(v);
while(!isEmpty(Q)) {
v = Dequeue(Q);
for (v的每個鄰接點w) {
if(!visited[w]) {
visited[w] = true;
Enqueue(w, Q);
}
}
}
}
**注:**使用隊列改遞歸爲循環
時間複雜度:(同上)
3. 圖不連通
**連通:**如果從v到w存在一條(無向)路徑,則稱v與w是連通的
**強連通:**如果從v到w存在雙向路徑,則稱v與w是強連通的
**路徑:**v到w的路徑是一系列頂點的集合,且任一對相鄰頂點間都有圖中的邊
**迴路:**起點等於終點的路徑
**連通圖:**圖中任意兩頂點均連通
連通分量:無向圖的極大連通子圖
-
極大頂點數:再加一個就不連通了
-
極大邊數:包含子圖中所有頂點相連的所有邊
[外鏈圖片轉存失敗(img-hftgLg0I-1567356455559)(C:\Users\alway\AppData\Roaming\Typora\typora-user-images\1567348540093.png)]
void ListComponents(Graph G) {
for (each v in G) {
if (!visited[v]) {
DFS(V);
}
}
}
**注:**每調用一次DFS(v)就把v所在的連通分量遍歷了一遍,BFS同理
4. 代碼實現
/* 鄰接表存儲的圖 - DFS */
void Visit( Vertex V )
{
printf("正在訪問頂點%d\n", V);
}
/* Visited[]爲全局變量,已經初始化爲false */
void DFS( LGraph Graph, Vertex V, void (*Visit)(Vertex) )
{ /* 以V爲出發點對鄰接表存儲的圖Graph進行DFS搜索 */
PtrToAdjVNode W;
Visit( V ); /* 訪問第V個頂點 */
Visited[V] = true; /* 標記V已訪問 */
for( W=Graph->G[V].FirstEdge; W; W=W->Next ) /* 對V的每個鄰接點W->AdjV */
if ( !Visited[W->AdjV] ) /* 若W->AdjV未被訪問 */
DFS( Graph, W->AdjV, Visit ); /* 則遞歸訪問之 */
}
/* 鄰接矩陣存儲的圖 - BFS */
/* IsEdge(Graph, V, W)檢查<V, W>是否圖Graph中的一條邊,即W是否V的鄰接點。 */
/* 此函數根據圖的不同類型要做不同的實現,關鍵取決於對不存在的邊的表示方法。*/
/* 例如對有權圖, 如果不存在的邊被初始化爲INFINITY, 則函數實現如下: */
bool IsEdge( MGraph Graph, Vertex V, Vertex W )
{
return Graph->G[V][W]<INFINITY ? true : false;
}
/* Visited[]爲全局變量,已經初始化爲false */
void BFS ( MGraph Graph, Vertex S, void (*Visit)(Vertex) )
{ /* 以S爲出發點對鄰接矩陣存儲的圖Graph進行BFS搜索 */
Queue Q;
Vertex V, W;
Q = CreateQueue( MaxSize ); /* 創建空隊列, MaxSize爲外部定義的常數 */
/* 訪問頂點S:此處可根據具體訪問需要改寫 */
Visit( S );
Visited[S] = true; /* 標記S已訪問 */
AddQ(Q, S); /* S入隊列 */
while ( !IsEmpty(Q) ) {
V = DeleteQ(Q); /* 彈出V */
for( W=0; W<Graph->Nv; W++ ) /* 對圖中的每個頂點W */
/* 若W是V的鄰接點並且未訪問過 */
if ( !Visited[W] && IsEdge(Graph, V, W) ) {
/* 訪問頂點W */
Visit( W );
Visited[W] = true; /* 標記W已訪問 */
AddQ(Q, W); /* W入隊列 */
}
} /* while結束*/
}