深度優先搜索的圖文介紹


1. 深度優先搜索介紹

圖的深度優先搜索(Depth First Search),和樹的先序遍歷比較類似。

它的思想:假設初始狀態是圖中所有頂點均未被訪問,則從某個頂點v出發,首先訪問該頂點,然后依次從它的各個未被訪問的鄰接點出發深度優先搜索遍歷圖,直至圖中所有和v有路徑相通的頂點都被訪問到。 若此時尚有其他頂點未被訪問到,則另選一個未被訪問的頂點作起始點,重復上述過程,直至圖中所有頂點都被訪問到為止。

顯然,深度優先搜索是一個遞歸的過程。

2. 深度優先搜索圖解

2.1 無向圖的深度優先搜索

下面以"無向圖"為例,來對深度優先搜索進行演示。

對上面的圖G1進行深度優先遍歷,從頂點A開始。

第1步:訪問A。 
第2步:訪問(A的鄰接點)C。 
    在第1步訪問A之后,接下來應該訪問的是A的鄰接點,即"C,D,F"中的一個。但在本文的實現中,頂點ABCDEFG是按照順序存儲,C在"D和F"的前面,因此,先訪問C。 
第3步:訪問(C的鄰接點)B。 
    在第2步訪問C之后,接下來應該訪問C的鄰接點,即"B和D"中一個(A已經被訪問過,就不算在內)。而由於B在D之前,先訪問B。 
第4步:訪問(C的鄰接點)D。 
    在第3步訪問了C的鄰接點B之后,B沒有未被訪問的鄰接點;因此,返回到訪問C的另一個鄰接點D。 
第5步:訪問(A的鄰接點)F。 
    前面已經訪問了A,並且訪問完了"A的鄰接點B的所有鄰接點(包括遞歸的鄰接點在內)";因此,此時返回到訪問A的另一個鄰接點F。 
第6步:訪問(F的鄰接點)G。 
第7步:訪問(G的鄰接點)E。

因此訪問順序是:A -> C -> B -> D -> F -> G -> E

 

2.2 有向圖的深度優先搜索

下面以"有向圖"為例,來對深度優先搜索進行演示。

對上面的圖G2進行深度優先遍歷,從頂點A開始。

第1步:訪問A。 
第2步:訪問B。 
    在訪問了A之后,接下來應該訪問的是A的出邊的另一個頂點,即頂點B。 
第3步:訪問C。 
    在訪問了B之后,接下來應該訪問的是B的出邊的另一個頂點,即頂點C,E,F。在本文實現的圖中,頂點ABCDEFG按照順序存儲,因此先訪問C。 
第4步:訪問E。 
    接下來訪問C的出邊的另一個頂點,即頂點E。 
第5步:訪問D。 
    接下來訪問E的出邊的另一個頂點,即頂點B,D。頂點B已經被訪問過,因此訪問頂點D。 
第6步:訪問F。 
    接下應該回溯"訪問A的出邊的另一個頂點F"。 
第7步:訪問G。

因此訪問順序是:A -> B -> C -> E -> D -> F -> G

無向圖的鄰接矩陣實現代碼:

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>

#define MAX 100

typedef struct graph
{
    char vexs[MAX];
    int vexnum;
    int edgnum;
    int matrix[MAX][MAX];
}Graph,*PGraph;

static int get_position(Graph g,char ch)
{
    int i;
    for(i=0;i<g.vexnum;i++)
        if(g.vexs[i]==ch)
            return i;
    return -1;
}

Graph* create_graph()
{
   char vexs[]={'A','B','C','D','E','F','G'};
   char edges[][2]={{'A','C'},{'A','D'},{'A','F'},{'B','C'},{'C','D'},{'E','G'},{'F','G'}};
   int vlen=sizeof(vexs)/sizeof(vexs[0]);
   int  elen=sizeof(edges)/sizeof(edges[0]);
   int i,p1,p2;
   Graph *pG;
   if((pG=(Graph*)malloc(sizeof(Graph)))==NULL)
        return NULL;
   memset(pG,0,sizeof(Graph));
   pG->vexnum=vlen;
   pG->edgnum=elen;
   for(i=0;i<pG->vexnum;i++)
   {
       pG->vexs[i]=vexs[i];
   }
   for(i=0;i<pG->edgnum;i++)
   {
       p1=get_position(*pG,edges[i][0]);
       p2=get_position(*pG,edges[i][1]);
       pG->matrix[p1][p2]=1;
       pG->matrix[p2][p1]=1;
   }
   return pG;
}

void print_graph(Graph G)
{
    int i,j;
    printf("matrix Graph:\n");
    for(i=0;i<G.vexnum;i++)
    {
        for(j=0;j<G.vexnum;j++)
            printf("%d ",G.matrix[i][j]);
        printf("\n");
    }
}

int first_vertex(Graph G,int v)
{
    int i;
    for(i=0;i<G.vexnum;i++)
        if(G.matrix[v][i]==1)
            return i;
    return -1;
}

int next_vertex(Graph G,int v,int w)
{
    int i;
    for(i=w+1;i<G.vexnum;i++)
        if(G.matrix[v][i]==1)
            return i;
    return -1;
}

void DFS(Graph G,int i,int *visited)
{
    visited[i]=1;
    int w;
    printf("%c ",G.vexs[i]);
    for(w=first_vertex(G,i);w>=0;w=next_vertex(G,i,w))
    {
        if(visited[w]==0)
            DFS(G,w,visited);
    }
}

void DFSTraverse(Graph G)
{
    int i;
    int visited[MAX];
    memset(visited,0,sizeof(visited));
    printf("DFS : \n");
    for(i=0;i<G.vexnum;i++)
        if(!visited[i])
            DFS(G,i,visited);
    printf("\n");
}

int main()
{
    Graph *pG;
    pG=create_graph();
    print_graph(*pG);
    printf("\n");
    DFSTraverse(*pG);
}

運行結果:

無向圖的鄰接表實現代碼:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#define MAX 100
typedef struct ENode
{
    int ivex;
    struct ENode *next_edge;
}ENode;

typedef struct VNode
{
    char data;
    ENode *first_edge;
}VNode;

typedef struct LGraph
{
    int vexnum;
    int edgnum;
    VNode vexs[MAX];
} LGraph;

static int get_position(LGraph g,char ch)
{
    int i;
    for(i=0;i<g.vexnum;i++)
        if(g.vexs[i].data==ch)
            return i;
    return -1;
}

LGraph* create_lgraph()
{
    char c1,c2;
    char vexs[]= {'A','B','C','D','E','F','G'};
    char edges[][2]= {{'A','C'},{'A','D'},{'A','F'},{'B','C'},{'C','D'},{'E','G'},{'F','G'}};
    int vlen=sizeof(vexs)/sizeof(vexs[0]);
    int elen=sizeof(edges)/sizeof(edges[0]);
    int i,p1,p2;
    ENode *node1,*node2;
    LGraph *pG;
    if((pG=(LGraph*)malloc(sizeof(LGraph)))==NULL)
        return NULL;
    memset(pG,0,sizeof(LGraph));
    pG->vexnum=vlen;
    pG->edgnum=elen;
    for(i=0;i<pG->vexnum;i++)
    {
        pG->vexs[i].data=vexs[i];
        pG->vexs[i].first_edge=NULL;
    }

    for(i=0;i<pG->edgnum;i++)
    {
        c1=edges[i][0];
        c2=edges[i][1];
        p1=get_position(*pG,c1);
        p2=get_position(*pG,c2);
        node1=(ENode*)malloc(sizeof(ENode));
        node1->ivex=p2;
        node1->next_edge=NULL;
        if(pG->vexs[p1].first_edge==NULL)
            pG->vexs[p1].first_edge=node1;
        else
        {
            ENode *tmp=pG->vexs[p1].first_edge;
            while(tmp->next_edge)
            {
                tmp=tmp->next_edge;
            }
            tmp->next_edge=node1;
        }
        node2=(ENode*)malloc(sizeof(ENode));
        node2->ivex=p1;
        node2->next_edge=NULL;
        if(pG->vexs[p2].first_edge==NULL)
            pG->vexs[p2].first_edge=node2;
        else
        {
            ENode *tmp=pG->vexs[p2].first_edge;
            while(tmp->next_edge)
            {
                tmp=tmp->next_edge;
            }
            tmp->next_edge=node2;
        }
    }
    return pG;
}

void print_lgraph(LGraph G)
{
    int i;
    ENode *node;
    printf("list Graph:\n");
    for(i=0;i<G.vexnum;i++)
    {
        printf("%d(%c): ",i,G.vexs[i].data);
        node=G.vexs[i].first_edge;
        while(node)
        {
            printf("%d(%c) ",node->ivex,G.vexs[node->ivex].data);
            node=node->next_edge;
        }
        printf("\n");
    }
    printf("\n");
}

int main()
{
    LGraph *pG;
    pG=create_lgraph();
    print_lgraph(*pG);
}

運行結果:

有向圖與無向圖的DFS一樣,只是創建圖的方式不一樣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM