1. 程式人生 > >資料結構——圖的兩種遍歷方法

資料結構——圖的兩種遍歷方法

遍歷定義:從已給的圖中某一頂點出發,沿著一些邊,訪遍圖中所有的頂點,且使每個頂點僅被訪問一次,就叫做圖的遍歷。

遍歷實質:找每個頂點的鄰接點的過程。

圖的特點:圖中可能存在迴路,且圖的任一頂點都可能與其它頂點相通,在訪問完某個頂點之後可能會沿著某些邊又回到了曾經         訪問過的頂點。

解決思路:可設定一個輔助陣列 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