圖的遍歷(資料結構)
阿新 • • 發佈:2019-02-15
- 深度優先遍歷
1)思路:選出起始頂點v,然後選取與v鄰接的一個頂點u(u未被訪問過),訪問u,讓後重覆上述操作,繼續選取u的一個未訪問過的頂點x,訪問後繼續重複,直至選取的某個點沒有未訪問過的鄰接點了,退回到最近一次訪問過的點, 選取下一個未訪問過的鄰接點,以此類推。
2)遞迴描述:選取起始頂點v,訪問,選取它的一個鄰接點,若未訪問過,則進行遞迴遍歷,如此可訪問與v連通的所有點。
3)非連通處理:若訪問完v的所有連通的點後,仍有未訪問過的點,選取下一個為訪問過的點作為起始點,重新進行遞迴遍歷操作。
4)程式碼實現:
Status DFS(MGraph &G,int v,Status (*Visit)(ElemType))
{
//遍歷一個連通分量,不限定圖的儲存結構,v為起始點下標(注意,DFS不能遍歷一整個非連通圖,只能遍歷一個連通分量)
Visit(v);
visited[v] = true;
//w是v的鄰接點,第一次先找到v的第一個鄰接點,進行dfs,在w的
//所有鄰接點都找到了後,返回到v這一層,再找v的第二個鄰接點,以此類推
for(int w = FirstAdjVex(G,v); w >= 0; w = NextAdjVex(G,w))
{
if(!visited[w])
DFS(G,w,Visit);
}
}
Status DFSTraverse(MGraph &G,int v,Status (*Visit)(int v))
{
for(v = 0;v < G.vexnum; ++v)
{
visited[v] = false;//表示所有頂點都為被訪問過
}
//因為可能此圖是一個非連通圖,如果要遍歷所有的點,在遍歷完一個連通分量之後,需要再遍歷另一個連通分量
for(v = 0; v < G.vexnum; ++v)
{
if(!visited[v])
DFS(G,v,Visit);//注意這裡把函式作為引數是怎麼傳遞的
}
}
2.廣度優先搜尋
1)思路:選取一個起始點v,逐個遍歷v的鄰接點,直至把v的所有鄰接點都遍歷了一遍,再從v的第一個鄰接點開始,逐個訪問v的第一個鄰接點的所有鄰接點,重複上述操作,直至遍歷完與v連通的所有點。
2)分析:用佇列儲存訪問過的元素,v是起始點,訪問v,v入隊,迴圈判斷條件只要佇列不為空,取出佇列頭元素,訪問其鄰接點並將鄰接點入隊,重複上述操作,直至佇列為空,也就遍歷完了與v連通的所有點。
3)非連通處理:遍歷完v所屬的連通分量,若仍有點未訪問,從從其開始,重新進行廣度優先搜尋。
4)程式碼實現:
Status BFS(MGraph &G,int v,Status (*Visit)(ElemType))
{
Visit(V);
visited[v] = true;
EnQueue(Q,v);
//佇列不為空
while(!IsEmpty(Q))
{
ElemType u;
DeQueue(Q,u);
for(ElemType w = FirstAdjNex(G,u);w >= 0; w = NextAdjVex(G,u,w))//NextAdjVex找除w外的鄰接點
{
if(!visited[w])
{
Visit(w);
visited[w] = true;
EnQueue(Q,w);
}
}
}
}
Status BFSTraverse(MGraph &G,Status (*Visit)(int v))
{
//不管是dfs,還是bfs,都需要初始化visited陣列為false
for(v = 0; v < G.vexnum; ++v)
{
visited[v] = false;
}
for(v = 0; v < G.vexnum; ++v)
{
if(!visited[v])
BFS(G,v,Visit);
}
}