資料結構——圖的兩種遍歷方法
遍歷定義:從已給的圖中某一頂點出發,沿著一些邊,訪遍圖中所有的頂點,且使每個頂點僅被訪問一次,就叫做圖的遍歷。
遍歷實質:找每個頂點的鄰接點的過程。
圖的特點:圖中可能存在迴路,且圖的任一頂點都可能與其它頂點相通,在訪問完某個頂點之後可能會沿著某些邊又回到了曾經 訪問過的頂點。
解決思路:可設定一個輔助陣列 visited [n ],用來標記每個被訪問過的頂點。它的初始狀態為0,在圖的遍歷過程中,一旦某一 個頂點i被訪問,就立即改 visited [i]為1,防止它被多次訪問。
圖常用的遍歷: 深度優先搜尋
廣度優先搜尋
圖的深度優先遍歷(Depth_First Search:DFS):
遍歷步驟:從圖中的某個頂點v出發,訪問此頂點,然後依次從v的未被訪問的鄰接點出發深度優先遍歷圖,直至圖中所有和v有 路徑相通的頂點都被訪問到;若此時圖中尚有頂點未被訪問,則另選圖中一個未被訪問的頂點作起始點,重複上述過程,直 至圖中所有頂點都被訪問到為止。
詳細歸納:
-
在訪問圖中某一起始頂點 v 後,由 v 出發,訪問它的任一鄰接頂點 w1;
-
再從 w1出發,訪問與 w1鄰接但還未被訪問過的頂點 w2;
-
然後再從 w2 出發,進行類似的訪問, …
-
如此進行下去,直至到達所有的鄰接頂點都被訪問過的頂點 u 為止。
-
接著,退回一步, 退到前一次剛訪問過的頂點,看是否還有其它未被訪問的鄰接頂點。
如果有, 則訪問此頂點,之後再從此頂點出發,進行與前述類似的訪問;
如果沒有, 就再退回一步進行搜尋。重複上述過程,直到連通圖中所有頂
點都被訪問過為止。
如圖所示,例1:
具體實現過程,例2:
深度優先遍歷程式設計演算法:(鄰接矩陣)
void DFS( Mgraph g,int v,int visited[])
{
/* 鄰接矩陣儲存,從頂點v出發,對圖g進行深度優先搜尋*/
int j;
printf("%d ",g.vexs[v]);
visited[v]=1; /*標識v被訪問過*/
for(j=0;j<g.vexnum;j++); /* */
{
if( g.arcs[v][j]==1&&visited[j]==0)/*j為v的鄰接點,未被訪問過*/
DFS(g,j,visited); /*從j出發遞迴呼叫DFS*/
}/*for*/
}/*DFS*/
void DFSTraverse(Mgraph g)
{
/*鄰接矩陣 深度優先搜尋*/
int v;
int visited[MAX_VERTEX_NUM];
for(v=0;v<g.vexnum;v++)
visited[v]=0; /*初始化visited陣列*/
for(v=0;v<g.vexnum;v++)
if(visited[v]==0)
DFS(g,v,visited);
/*從未被訪問過的v出發, DFS搜尋*/
}
深度優先遍歷程式設計演算法:(鄰接表)
void DFS(ALGraph g,int v,int visited[])
{
/*從頂點v出發,對圖g進行深度優先搜尋*/
ArcNode *p;
int w;
printf("%d ",g.adjlist[v].data);
visited[v]=1; /*標識v被訪問過*/
p=g.adjlist[v].firstarc; /*p指向第v個單鏈表的頭指標*/
while(p)
{
w=p->adjvex; /*w為v的鄰接點*/
if(visited[w]==0) /*若w未被訪問*/
DFS(g,w,visited); /*從w出發遞迴呼叫DFS*/
p=p->nextarc; /*找v的下一個鄰接點*/
}/*while*/
}/*DFS*/
void DFSTraverse(ALGraph g)
{
/*鄰接表 深度優先搜尋*/
int v;
int visited[MAX_VERTEX_NUM];
for(v=0;v<g.vexnum;v++)
visited[v]=0; /*初始化visited陣列*/
for(v=0;v<g.vexnum;v++)
if(visited[v]==0)
DFS(g,v,visited);
/*從未被訪問過的v出發, DFS搜尋*/
}
圖的廣度優先遍歷(Breadth_First Search:BFS):
基本思想:— 模仿樹的層次遍歷過程。
遍歷步驟: 在訪問了起始點v之後,依次訪問 v的鄰接點;然後再依次(順序)訪問這些點(下一層)中未被訪問過的鄰接點; 直到所有頂點都被訪問過為止
具體實現過程,例2:
廣度優先遍歷程式設計演算法:(鄰接表)
BFSTraverse(ALGraph g)
{
// 鄰接表儲存 BFS 演算法
QElemType v,w,u;
SqQueue Q; ArcNode *p;
for(v=0;v<g.vexnum;v++)
visited[v]=0; //初始化visited陣列
InitQueue(&Q); //佇列Q初始化
for(v=0;v<g.vexnum ;v++) //從v出發廣度優先搜尋
{
if (!visited[v])
{
visited[v]=1;
printf("%d ",v); //輸出v
EnQueue(&Q,v); //v入隊
while(!EmptyQueue(Q)) //佇列Q不空
{
DeQueue(&Q,&u); // u出隊
p=g.adjlist[u].firstarc ;
while(p) //依次訪問u的鄰接點
{
w=p->adjvex;
if(!visited[w])
{
visited[w]=1;
printf("%d ",w);
EnQueue(&Q,w); //w 入隊
}
p=p->nextarc ; //p指向下一個鄰接點
}//end of while
}//end of while
}//end of if
}//end of for
}//end of BFSTravers