1. 程式人生 > >基於鄰接表儲存的圖的深度優先和廣度優先遍歷

基於鄰接表儲存的圖的深度優先和廣度優先遍歷

一.深度優先遍歷是連通圖的一種遍歷方法:

  設x是當前被訪問頂點,在對x做過訪問標記後,選擇一條從x出發的未檢測過的邊(x,

y)。若發現頂點y已訪問過,則重新選擇另一條從x出發的未檢測過的邊,否則沿邊(x,y)

到達未曾訪問過的y,對y訪問並將其標記為已訪問過;然後從y開始搜尋,直到搜尋完從y

出發的所有路徑,即訪問完所有從y出發可達的頂點之後,才回溯到頂點x,並且再選擇一

條從x出發的未檢測過的邊。上述過程直至從x出發的所有邊都已檢測過為止。


二.廣度優先遍歷是連通圖的一種遍歷方法:

1、從圖中某個頂點V0出發,並訪問此頂點;


2、從V0出發,訪問V0的各個未曾訪問的鄰接點W1,W2,…,Wk;然後,依次從W1,W2,


…,Wk出發訪問各自未被訪問的鄰接點;


3、重複步驟2,直到全部頂點都被訪問為止。


程式碼如下:

//鄰接表深度優先遍歷和廣度優先遍歷 
#include<stdio.h>  
#include<stdlib.h>

#define MaxVex 255 
#define TRUE   1  
#define FALSE  0
 
typedef char VertexType;  //頂點型別
typedef int Bool;
Bool visited[MaxVex];  
//記錄圖中節點訪問狀態 typedef struct EdgeNode { //邊表節點 int adjvex; //該鄰接點在頂點陣列中的下標 struct EdgeNode *next; //鏈域 指向下一個鄰接點 }EdgeNode; typedef struct VertexNode { //頭節點 VertexType data; //頂點資訊 EdgeNode *firstedge; //邊表頭指標 }VertexNode,AdjList[MaxVex]; //頂點陣列 typedef struct Graph{ AdjList adjList;
int numVertexes,numEdges; //圖中當前的結點數以及邊數 }Graph,*GraphAdjList; //佇列定義及相關操作 typedef struct LoopQueue{ int data[MaxVex]; int front,rear; }LoopQueue,*Queue; //佇列結構 void initQueue(Queue &Q){ Q->front=Q->rear=0; } Bool QueueEmpty(Queue &Q){ if(Q->front == Q->rear){ return TRUE; }else{ return FALSE; } } Bool QueueFull(Queue &Q){ if((Q->rear+1)%MaxVex == Q->front){ return TRUE; }else{ return FALSE; } } // 隊尾插入元素 void EnQueue(Queue &Q,int e){ if(!QueueFull(Q)){ Q->data[Q->rear] = e; Q->rear = (Q->rear+1)%MaxVex; } } //隊頭刪除元素 void DeQueue(Queue &Q,int *e){ if(!QueueEmpty(Q)){ *e = Q->data[Q->front]; Q->front = (Q->front+1)%MaxVex; } } //建立無向圖的鄰接表結構 void CreateALGraph(GraphAdjList &G){ int i, j, k; if(G==NULL){ G = (GraphAdjList)malloc(sizeof(Graph)); } printf("輸入圖的結點數以及邊數: "); scanf("%d%d",&G->numVertexes,&G->numEdges); fflush(stdin); printf("===========================\n"); printf("輸入各個頂點的資料:\n"); for (i=0; i<G->numVertexes; ++i){ printf("頂點%d: ",i+1); scanf("%c", &(G->adjList[i].data)); G->adjList[i].firstedge = NULL; fflush(stdin); } printf("===========================\n"); for (k=0; k<G->numEdges; ++k){ printf("輸入(vi,vj)上的頂點序號: "); scanf("%d%d",&i,&j); EdgeNode *ptrEdgeNode = (EdgeNode*)malloc(sizeof(EdgeNode)); ptrEdgeNode->adjvex = j; ptrEdgeNode->next = G->adjList[i].firstedge; G->adjList[i].firstedge = ptrEdgeNode; ptrEdgeNode = (EdgeNode*)malloc(sizeof(EdgeNode)); ptrEdgeNode->adjvex = i; ptrEdgeNode->next = G->adjList[j].firstedge; G->adjList[j].firstedge = ptrEdgeNode; } } void DFS(GraphAdjList &G, int i){ visited[i] = TRUE; printf("%c ", G->adjList[i].data); EdgeNode *p = G->adjList[i].firstedge; while(p){ if(!visited[p->adjvex]){ DFS(G,p->adjvex); //遞迴深度遍歷 } p= p->next; } } //深度優先遍歷 void DFSTraverse(GraphAdjList &G){ int i; for (i=0; i<G->numVertexes; ++i){ visited[i] = FALSE; //初始化訪問陣列visited的元素值為false } for (i=0; i<G->numVertexes; ++i){ if(!visited[i]){ //節點尚未訪問 DFS(G,i); } } } //圖的廣度優先遍歷 void BFSTraverse(GraphAdjList &G){ int i; Queue Q = (Queue)malloc(sizeof(LoopQueue)); for (i=0; i<G->numVertexes; ++i){ visited[i] = FALSE; } initQueue(Q); for (i=0; i<G->numVertexes; ++i){ if(!visited[i]){ visited[i] = TRUE; printf("%c ", G->adjList[i].data); EnQueue(Q, i); while (!QueueEmpty(Q)){ DeQueue(Q, &i); EdgeNode *p = G->adjList[i].firstedge; while (p){ if (!visited[p->adjvex]){ visited[p->adjvex] = TRUE; printf("%c ", G->adjList[p->adjvex].data); EnQueue(Q, p->adjvex); } p = p->next; } } } } } int main(){ GraphAdjList G = NULL; CreateALGraph(G); printf("\n圖的深度優先遍歷為: "); DFSTraverse(G); printf("\n圖的廣度優先遍歷為: "); BFSTraverse(G); printf("\n"); return 0; }