圖的深度遍歷和廣度遍歷


近段時間又回顧了下數據結構中的圖,我之前的有一篇博文介紹了圖與線性表和樹的區別與聯系。 並且就圖的存儲和圖的創建也做了一些簡單的說明,

這一篇我將着重說說圖的兩種基本的遍歷方法,深度遍歷和廣度遍歷。 深度遍歷:  深度遍歷類似於樹的先根遍歷,是樹的先根遍歷的推廣。假設初始狀態是圖中所有頂點未曾被訪問,則深度遍歷可從圖中 某個頂點v出發,訪問此頂點,然后依次從v的未被訪問的鄰接點出發深度優先遍歷圖,直至圖中所有與v有路徑的頂點都被訪問到,若此時 圖中尚有頂點未被訪問,則另選圖中一個未被訪問的頂點作為起始點,重復上述過程,直至圖中所有頂點都被訪問到為止。 其具體的代碼實現如下:

int DFSTraverse(MGraph G)

{

  int v;  

  printf("\n深度遍歷輸出 : \n");  

  for(v = 0; v < G.vexnum; v++)  

  {   

    visited[v] = 0;  

  }  

  for(v = 0; v < G.vexnum; v++)  

  {   

    if(visited[v] == 0)   

    {    

      DFS(G, v);    

      printf("\n");   

    }  

  }  

  return true;

}

int DFS(MGraph G, int v)   

{  

  int w;  

  visited[v] = 1;  

  printf("%s  ", G.vexs[v]);  

  for(w = 0; w < G.vexnum; w++)  

  {   

    if(G.arcs[v][w].adj ==1 && visited[w] == 0)   

    {    

      DFS(G,w);   

    }  

  }  

  return true;

}

其實質是運用了遞歸思想,在遍歷圖中時,對圖中的每個頂點之多調用一次DNS函數,因為一旦某個頂點唄標志城已被訪問, 就不再從它出發進行搜索了,因此遍歷圖的實質上是對每個頂點查找器鄰接點的過程。

廣度遍歷:  

  廣度優先搜索遍歷類似於樹的按層次遍歷的過程。假設從圖中某個頂點v出發,在訪問了v之后依次訪問v的各個未曾訪問過的鄰接點,然后分別 從這些鄰接點出發依次訪問它們的鄰接點,並使“先被訪問的頂點的鄰接點”先與“后被訪問的鄰接點”被訪問,直至圖中所有已被訪問的鄰接點都被訪問到, 若此時圖中尚有頂點未被訪問到,則另選圖中一個未被訪問的頂點作為起始點,重復上述操作,直至圖中所有頂點都被訪問到為止。 其具體代碼實現如下:

int QueueInit(Queue *sq)

{  

  if(sq)  

  {   

    sq->front = 0;   

    sq->rear = 0;  

  }  

  else   

    return false;  

  return true;  

}

int QueueIsEmpty(Queue sq)

{  

  if(sq.front == sq.rear)   

    return true;  

  else   

    return false;

}

int EnQueue(Queue *sq, int x)

{  

  if(sq->front == (sq->rear+1)%MAX_VERTEX_NUM)  

  {   

    printf("Queue is full!\n");   

    return false;  

  }  else  

  {   

    sq->data[sq->rear] = x;   

    sq->rear = (sq->rear+1)%MAX_VERTEX_NUM;  

  }

}

int OutQueue(Queue *sq)

{  

  if(QueueIsEmpty(*sq))  

  {   

    printf("Queue is Empty!\n");   

    return false;  

  }  else  

  {   

    sq->front = (sq->front+1)%MAX_VERTEX_NUM;  

  }

}

int QueueFront(Queue sq, int *e)

{  

  if(QueueIsEmpty(sq))  

  {   

    printf("Queue is full!\n");   

    return false;  

  }  else  

  {   

    *e = sq.data[sq.front];   

    return true;  

  }

}

int BFSTraverse(MGraph G)

{  

  int v;  

  printf("廣度遍歷 : \n");     

  for(v = 0; v < G.vexnum; v++)  

  {   

    visited[v] = 0;  

  }   

  for(v = 0; v < G.vexnum; v++)  

  {   

    if(visited[v] == 0)   

    {    

      BFS(G, v);    

      printf("\n");   

    }  

  }   

  return true;

}

int BFS(MGraph G, int v)

{  

  int v1, v2;  

  Queue sq;  

  QueueInit(&sq);  

  EnQueue(&sq, v);  

  visited[v] = 1;  

  printf("%s  ", G.vexs[v]);   

  while(QueueIsEmpty(sq) == false)  

  {   

    QueueFront(sq, &v1);   

    OutQueue(&sq);      

    for(v2 = 0; v2 < G.vexnum; v2++)   

    {    

      if(G.arcs[v1][v2].adj != 0 && visited[v2] == 0)    

      {     

        EnQueue(&sq, v2);     

        visited[v2] = 1;     

        printf("%s  ", G.vexs[v2]);    

      }   

    }    

  }  

  return true;

}

對於圖的廣度優先遍歷的試下來說,運用了隊列的特點,每一個頂點之多進一次隊列,便利圖的實質上是通過邊或者弧 找鄰接點的過程。

從上可以看出,其實廣度遍歷和深度遍歷它們兩者的時間復雜度是一樣的,兩者的不同之處僅僅在於對頂點訪問的順序不同而已。


免責聲明!

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



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