1. 程式人生 > >廣度優先搜尋,圖的遍歷

廣度優先搜尋,圖的遍歷

1、  佇列

(1)       定義

    佇列也是一種運算受限的線性表。在這種線性表上,插入限定在表的某一端進行,刪除限定在表的另一端進行。允許插入的一端稱為隊尾,允許刪除的一端稱為隊頭。

    特點:佇列中資料元素的入隊和出隊過程是按照“先進先出” 的原則進行的。因此,佇列又稱為“先進先出”的線性表,簡稱FIFO

(2)       

實現-鏈佇列

佇列的鏈式儲存結構簡稱為鏈隊。它實際上是一個同時帶有首指標和尾指標的單鏈表。頭指標指向表頭結點,而尾指標則指向隊尾元素。從隊尾插入,從隊首刪除。空的鏈隊對列的判決條件是頭指標和尾指標均指向頭結點。

10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地

鏈隊運算指標變化情況:

10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地

2、  廣度優先搜尋的演算法思想

廣度優先搜尋遍歷類似於樹的按層次遍歷。

    對於無向連通圖,廣度優先搜尋是從圖的某個頂點v0出發,在訪問v0之後,依次搜尋訪問v0的各個未被訪問過的鄰接點w1w2,…。然後順序搜尋訪問w1的各未被訪問過的鄰接點,w2的各未被訪問過的鄰接點,…。即從

v0開始,由近至遠,按層次依次訪問與v0有路徑相通且路徑長度分別為12,…的頂點,直至連通圖中所有頂點都被訪問一次。

廣度優先搜尋的順序不是唯一的。

具體描述如下:

設圖G的初態是所有頂點均未訪問,在中任選一頂點i作為初始點,則廣度優先搜尋的基本思想是:

1)從圖中的某個頂點V出發,訪問之;並將其訪問標誌置為已被訪問,即visited[i]=1

2)依次訪問頂點V的各個未被訪問過的鄰接 點,將V的全部鄰接點都訪問到;

3分別從這些鄰接點出發,依次訪問它們的未被訪問過的鄰接點,並使“先被訪問的頂點的鄰接點”先於“後被訪問的頂點的鄰接點”被訪問,直到圖中所有已被訪問過的頂

 點的鄰接點都被訪問到。

依此類推,直到圖中所有頂點都被訪問完為止 

廣度優先搜尋在搜尋訪問一層時,需要記住已被訪問的頂點,以便在訪問下層頂點時,從已被訪問的頂點出發搜尋訪問其鄰接點。所以在廣度優先搜尋中需要設定一個佇列Queue,使已被訪問的頂點順序由隊尾進入佇列。在搜尋訪問下層頂點時,先從隊首取出一個已被訪問的上層頂點,再從該頂點出發搜尋訪問它的各個鄰接點。

如下圖(c)中為對圖(a)的遍歷:

10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地

按照廣度優先演算法,其遍歷順序為:

10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地

3、  廣度優先搜尋演算法的C語言描述

10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地10、廣度優先搜尋,圖的遍歷 - 墨涵 - 墨涵天地

 

4、  廣度優先搜尋演算法的C語言實現

   #include "stdio.h"

#define MAX_VERTEX_NUM 20

#include "conio.h"

#include "stdlib.h"

 

typedef char VertexType;

//我們依然用鄰接表來作圖的儲存結構

typedef struct ArcNode{

       int adjvex;

       struct ArcNode *nextarc;

       int info;

}ArcNode;  //表結點型別

 

typedef struct VNode{

       VertexType data;

       ArcNode *firstarc;

}VNode,AdjList[MAX_VERTEX_NUM]; //頭結點

 

typedef struct{

       AdjList vertices;  //鄰接表

       int vexnum,arcnum;

}ALGraph;

 

typedef struct Qnode{       //鏈隊結點的型別

    int data;

    struct Qnode *next;

}Qnode,*QueuePtr;

 

typedef struct

{         //鏈隊指標型別

   QueuePtr front;

   QueuePtr rear;

}LinkQueue;

 

int visited[MAX_VERTEX_NUM];

 

int LocateVex(ALGraph G,char u)

    {

       int i;

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

           { if(u==G.vertices[i].data) return i; }

       if (i==G.vexnum) {printf("Error u!\n");exit(1);}

       return 0;

    }

 

void InitQueue(LinkQueue &Q)

{

  Q.front=Q.rear=(QueuePtr)malloc(sizeof(Qnode));

  if(!Q.front) exit(1); //儲存分配失敗

  Q.front->next=NULL;

 }

 

void EnQueue(LinkQueue &Q,int e)

{ QueuePtr p;

  p=(QueuePtr)malloc(sizeof(Qnode));

  p->data=e;

  p->next=NULL;

  Q.rear->next=p;

  Q.rear=p;

}

 

int QueueEmpty(LinkQueue &Q)

{

       return(Q.front==Q.rear? 1:0);

}

 

void DeQueue(LinkQueue &Q,int &e)

{ QueuePtr p;

  if(QueueEmpty(Q))

  {

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

    exit(1);

  }//if

  p=Q.front->next;

  e=p->data;

  Q.front->next=p->next;

  if(Q.front->next==NULL) Q.rear=Q.front;

  free(p);

 }

 

 

void CreateALGraph_adjlist(ALGraph &G)

    {    

       int i,j,k,w; 

       char v1,v2,enter;

       ArcNode *p;

       printf("Input vexnum & arcnum:\n");

       scanf("%d",&G.vexnum);

       scanf("%d",&G.arcnum);

       printf("Input Vertices(以回車隔開各個資料):\n");

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

              {     scanf("%c%c",&enter,&G.vertices[i].data);//注意點解說

                     G.vertices[i].firstarc=NULL;

              }//for

      

printf("Input Arcs(v1,v2,w)以回車分開各個資料:\n");

   for (k=0;k<G.arcnum;k++)

       {

              scanf("%c%c",&enter,&v1);

              scanf("%c%c",&enter,&v2);

              //scanf("%d",&w);

              i=LocateVex(G,v1);

              j=LocateVex(G,v2);

              p=(ArcNode*)malloc(sizeof(ArcNode));

              p->adjvex=j;  

              //p->info = w;

              p->nextarc=G.vertices[i].firstarc; //前插法,即每次都插入到頭結點的後面

              G.vertices[i].firstarc=p;

              printf("Next\n");

       }//for     

   return;

}//CreateALGraph_adjlist

 

void BFSTraverse(ALGraph &G)

{

LinkQueue Q;

for(int v=0;v<G.vexnum;++v) visited[v]=false;

InitQueue(Q);

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

       if(!visited[v])

       {

       EnQueue(Q,v);

       while(!QueueEmpty(Q))

       {

       int u;      

       DeQueue(Q,u);

       visited[u]=true;

       printf("->%c",G.vertices[u].data);//visit一下

       for(ArcNode *w=G.vertices[u].firstarc;w;w=w->nextarc)

              if(!visited[w->adjvex]) EnQueue(Q,w->adjvex);

       }//while

       }//if

}//BFSTraverse

 

int main()

{

ALGraph G;

CreateALGraph_adjlist(G);

BFSTraverse(G);

}

5、  廣度優先搜尋和深度優先搜尋

深度優先搜尋演算法涉及的是堆疊,廣度優先搜尋涉及的是佇列。