圖的遍歷(DFS、BFS)使用鄰接矩陣(陣列)作為儲存結構--C語言
阿新 • • 發佈:2019-02-07
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#define MAX_VERTEX_NUM 20 //最大頂點個數
#define INFINITY INT_MAX //最大值∞
typedef char VertexType; //頂點向量型別
typedef int VRType;
typedef int InfoType;
typedef int QElemType;
//圖的陣列儲存表示
typedef struct{
VertexType vexs[MAX_VERTEX_NUM]; //頂點向量
VRType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];; //鄰接矩陣,於無權圖1、0表示兩個頂點是否相鄰,對於有權圖為權值
int vexnum,arcnum; //圖的頂點數和弧數
}MGraph;
bool visited[MAX_VERTEX_NUM]; //標記頂點是否被訪問,訪問為true,否則為false
//查詢頂點在頂點向量中的位置
int locateVertex(MGraph umg, VertexType v)
{
int i;
for(i=0;i<umg.vexnum;i++)
{
if(v == umg.vexs[i])
return i;
}
return -1;
}
//建立無向(有向)無權圖
createUMGraph(MGraph *umg)
{
int i,j,v;
char v1,v2;
printf("輸入無權圖的頂點數和邊數\n");
scanf("%d %d",&(*umg).vexnum,&(*umg).arcnum);
for(v=0;v<(*umg).vexnum;v++)
visited[v] = false ;
getchar();
printf("輸入頂點名稱\n");
for(v=0;v<(*umg).vexnum;v++)
{
printf("輸入第%d個頂點名稱:",v);
scanf("%c",&(*umg).vexs[v]);
getchar();
}
//初始化鄰接矩陣
for(i=0;i<(*umg).vexnum;i++)
for(j=0;j<(*umg).vexnum;j++)
(*umg).arcs[i][j] = 0;
//將圖中相鄰的頂點的鄰接矩陣值設為1,不相鄰仍為0
printf("輸入邊的資訊,輸入邊的兩個頂點名稱v1 v2\n");
for(v=0;v<(*umg).arcnum;v++)
{
printf("輸入第%d條邊兩個頂點:",v);
scanf("%c %c",&v1,&v2);
getchar();
printf("\n");
i = locateVertex(*umg,v1);
j = locateVertex(*umg,v2);
// (*umg).arcs[i][j] = (*umg).arcs[j][i] = 1; //由於是無向圖,因此一條邊關聯兩個頂點
(*umg).arcs[i][j] = 1; //有向圖,邊為單向
}
}
//建立無向(有向)有權圖
createMGraph(MGraph *mg)
{
int i,j,v,w;
char v1,v2;
printf("輸入有權圖的頂點數和邊數\n");
scanf("%d %d",&(*mg).vexnum,&(*mg).arcnum);
for(v=0;v<(*mg).vexnum;v++)
visited[v] = false;
getchar();
printf("輸入頂點名稱\n");
for(v=0;v<(*mg).vexnum;v++)
{
printf("輸入第%d個頂點名稱:",v);
scanf("%c",&(*mg).vexs[v]);
getchar();
}
//初始化鄰接矩陣
for(i=0;i<(*mg).vexnum;i++)
for(j=0;j<(*mg).vexnum;j++)
(*mg).arcs[i][j] = INFINITY;
//將圖中相鄰的頂點的鄰接矩陣值設為邊的權值
printf("輸入邊的資訊,輸入邊的兩個頂點名稱和權值v1 v2 w\n");
for(v=0;v<(*mg).arcnum;v++)
{
printf("輸入第%d條邊兩個頂點和權值:",v);
scanf("%c %c %d",&v1,&v2,&w);
getchar();
i = locateVertex(*mg,v1);
j = locateVertex(*mg,v2);
// (*mg).arcs[i][j] = (*mg).arcs[j][i] = w; //由於是無向圖,因此一條邊關聯兩個頂點
(*mg).arcs[i][j] = w; //有向圖,邊為單向
}
}
//列印圖的臨界矩陣
void print(MGraph G)
{
int i,j;
printf("圖的鄰接矩陣\n");
for(i=0;i<G.vexnum;i++)
{
for(j=0;j<G.vexnum;j++)
{
if(G.arcs[i][j]!=INFINITY)
printf("%d ",G.arcs[i][j]);
else
printf("∞ ");
}
printf("\n");
}
printf("\n");
}
//深度優先遍歷圖
int FirstAdjVex(MGraph G,int v)
{ //獲取與頂點v相鄰的第一個頂點下標
int i;
for(i=0;i<G.vexnum;i++)
{
if(G.arcs[v][i]!=0 && G.arcs[v][i]!=INFINITY && !visited[i])
return i;
}
return -1;
}
int NextAdjVex(MGraph G,int v,int w)
{ //得到v的下一個未被訪問的相鄰頂點下標
int i;
for(i=w;i<G.vexnum;i++)
{
if(G.arcs[v][i]!=0 && G.arcs[v][i]!=INFINITY && !visited[i])
return i;
}
return -1;
}
void DFS(MGraph G,int v)
{
int w;
visited[v] = true;
printf("%c ",G.vexs[v]); //訪問第v個頂點
for(w = FirstAdjVex(G,v); w >= 0;w = NextAdjVex(G,v,w))
if(!visited[w])
DFS(G,w); //對v的尚未訪問的鄰接頂點w遞迴呼叫DFS
}
void DFSTraverse(MGraph G)
{
printf("深度優先遍歷序列:");
int v;
for(v = 0; v<G.vexnum;v++)
visited[v] = false;
for(v=0;v<G.vexnum;v++)
if(!visited[v])
DFS(G,v);
printf("\n");
}
//廣度優先遍歷
//建立用於廣度優先遍歷的佇列
typedef struct QNode
{
QElemType data;
struct QNode *qnext;
}QNode,*PQNode;
typedef struct Queue
{
PQNode front;
PQNode rear;
}Queue,*PQueue;
//初始化一個空佇列
PQueue initQueue()
{
PQueue pqueue = (PQueue)malloc(sizeof(Queue));
PQNode pqnode = (PQNode)malloc(sizeof(QNode));
if(pqnode==NULL)
{
printf("佇列頭空間申請失敗!\n");
exit(-1);
}
pqueue->front = pqueue->rear = pqnode;
pqnode->qnext = NULL;
return pqueue;
}
//隊尾入隊
void enQueue(PQueue pqueue,QElemType data)
{
PQNode pqnode = (PQNode)malloc(sizeof(QNode));
if(pqnode==NULL)
{
printf("佇列結點申請失敗!\n");
exit(-1);
}
pqnode->data = data;
pqnode->qnext = NULL;
pqueue->rear->qnext = pqnode;
pqueue->rear = pqnode;
}
//判斷佇列是否為空
bool isEmpty(PQueue pqueue)
{
if(pqueue->front == pqueue->rear)
return true;
return false;
}
//隊頭出隊
QElemType deQueue(PQueue pqueue)
{
if(isEmpty(pqueue))
{
printf("佇列為空\n");
exit(-1);
}
PQNode pqnode = pqueue->front->qnext;
pqueue->front->qnext = pqnode->qnext;
if(pqnode == pqueue->rear)
pqueue->rear = pqueue->front;
QElemType data = pqnode->data;
free(pqnode);
return data;
}
void BFSTraverse(MGraph G)
{
printf("廣度優先遍歷序列:");
int i,v,w;
for(i=0;i<G.vexnum;i++)
visited[i] = false;
PQueue pqueue = initQueue(); //初始化輔助佇列
for(i=0;i<G.vexnum;i++)
{
if(!visited[i]) //i未被訪問
{
visited[i] = true;
printf("%c ",G.vexs[i]);
enQueue(pqueue,i);
while(!isEmpty(pqueue))
{
v = deQueue(pqueue); //隊頭元素出隊
for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w))
if(!visited[w]) //w為v的尚未訪問的鄰接頂點
{
visited[w] = true;
printf("%c ",G.vexs[w]);
enQueue(pqueue,w);
}
}
}
}
printf("\n");
}
int main()
{
// MGraph umg; //無權圖
// createUMGraph(&umg); //建立無權圖
// print(umg);
MGraph mg;
createMGraph(&mg);
print(mg);
DFSTraverse(mg);
BFSTraverse(mg);
return 0;
}