基於鄰接表儲存的圖的深度優先和廣度優先遍歷
阿新 • • 發佈:2018-12-09
一.深度優先遍歷是連通圖的一種遍歷方法:
設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;
}