圖的鄰接表表示及其BFS遍歷
有下面這張圖:
假設該圖為有向圖,邊的指向均為小序號指向大序號。那么對該圖的BFS遍歷如下(假設從序號0的節點開始遍歷):
遍歷結果應為:
a b f c g i d e h
BFS遍歷類似於樹的層序遍歷,需要用到隊列。下面是程序代碼:
1.隊列定義和相關操作
文件1 queue.h
//1.queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include<stdio.h>
#define MAX 100
typedef int MyType; //可以修改為用戶需要的數據類型
typedef struct
{
MyType node[MAX];
int s;
int e;
}queue;
MyType pop(queue* a);
void push(queue* a,MyType b);
void initQueue(queue* a);
int isEmpty(queue* a);
#endif
文件2 queue.c
//2.queue.c
#include "queue.h"
MyType pop(queue* a)
{
MyType tmp ;
tmp = a->node[a->s];
a->s++;
return tmp;
}
void push(queue* a,MyType b)
{
if(a->e==MAX)
fprintf(stderr,"ERROR:the queue is full,can not push again!\n");
else
{
a->node[a->e]=b;
a->e++;
}
}
void initQueue(queue* a)
{
a->s = 0;
a->e = 0;
}
int isEmpty(queue* a)
{
if(a->e == a->s)
return 1;
return 0;
}
2.圖的鄰接表表示及其遍歷操作
文件3 graph.h
//graph.h
#ifndef GRAPH_H
#define GRAPH_H
#include<stdio.h>
#include<stdlib.h>
#include "queue.h"
#define MAXVEX 100
#define true 1
typedef char VertexType;
typedef int EdgeType;
typedef struct EdgeNode /*邊表結點*/
{
int adjvex; //存儲頂點下標
EdgeType weight;
struct EdgeNode* next;
}EdgeNode;
typedef struct VertexNode /*頂點表節點*/
{
VertexType data;
EdgeNode* firstedge;
}VertexNode,AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numVertexes,numEdges;
}GraphAdjList;
void CreatGraph(GraphAdjList *g);
void DFS(GraphAdjList *g,int i);
void DFSTravel(GraphAdjList *g);
void BFSTravel(GraphAdjList *g);
#endif
文件4 graph.c
#include "graph.h"
int visited[MAXVEX]={0};
void CreatGraph(GraphAdjList *g)
{
int i,j,k;
EdgeNode *e;
scanf("%d%d",&g->numVertexes,&g->numEdges);
char c;
//gettchar();
for(i=0;i<g->numVertexes;i++)
{
while((c=getchar())=='\n'||c==' '); //排除空格和'\n'
g->adjList[i].data = c;
// scanf("%c",&g->adjList[i].data);
g->adjList[i].firstedge = NULL;
}
for(k=0;k<g->numEdges;k++)
{
scanf("%d%d",&i,&j);
e=(EdgeNode*)malloc(sizeof(EdgeNode));
e->adjvex = j;
e->next = g->adjList[i].firstedge;
g->adjList[i].firstedge= e;
/*e=(EdgeNode*)malloc(sizeof(EdgeNode));如果圖為無向圖,則需要加上這段代碼
e->adjvex = i;
e->next = g->adjList[j].firstedge;
g->adjList[j].firstedge= e;*/
}
}
void DFS(GraphAdjList *g,int i)
{
EdgeNode *p;
visited[i]=1;
printf("%c ",g->adjList[i].data);
p = g->adjList[i].firstedge;
while(p)
{
if(visited[p->adjvex]==0)
DFS(g,p->adjvex);
p=p->next;
}
}
void DFSTravel(GraphAdjList *g)
{
int i;
for(i=0;i<g->numVertexes;i++)
{
if(!visited[i])
DFS(g,i); //主要是為了處理非連通圖,如果為連通圖,那么DFS函數執行一次即可遍歷全部節點
}
}
void BFSTravel(GraphAdjList *g)
{
int i;
int tmp;
EdgeNode *p;
queue q;
for(i=0;i<g->numVertexes;i++)
visited[i]= 0;
initQueue(&q);
for(i=0;i<g->numVertexes;i++)
{
if(!visited[i])
{
visited[i]=1;
printf("%c ",g->adjList[i].data);
push(&q,i);
while(!isEmpty(&q))
{
tmp = pop(&q);
p = g->adjList[tmp].firstedge;
while(p)
{
if(!visited[p->adjvex])
{
visited[p->adjvex]=1;
printf("%c ",g->adjList[p->adjvex].data);
push(&q,p->adjvex);
}
p = p->next;
}
}
}
}
}
3.main.c文件
main.c文件非常簡單
文件5 main.c
#include<stdio.h>
#include"graph.h"
int main()
{
GraphAdjList g;
CreatGraph(&g);
BFSTravel(&g);
return 0;
}
4.makefile文件
為了方便編譯,寫一個簡單的makefile文件
文件6 makefile
OBJ = main.o queue.o graph.o
TARGET = main.out
${TARGET}:${OBJ}
gcc -o ${TARGET} ${OBJ}
main.o:main.c
gcc -c main.c
queue.o:queue.c
gcc -c queue.c
graph.o:graph.c
gcc -c graph.c
clean:
rm -rf ${TARGET} ${OBJ}
5.執行結果
整個目錄文件如下:
執行make,生成可執行文件,然后運行程序:
可見程序運行結果和分析得到的結果是一致的。
代碼下載:https://github.com/zkangHUST/DataStructure/tree/master/Graph