//
// main.cpp
// Grpah_DFS_BFS
//
// Created by duanqibo on 2019/7/3.
// Copyright © 2019年 duanqibo. All rights reserved.
// 無向圖和有向圖的深度遍歷和廣度遍歷
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxVerNum 20 //圖的最大頂點數
#define MaxSize 30 //隊列的最大容量
typedef enum {False,True} Bool;
typedef struct ArcNode
{
int adjvex; //該弧所指向的頂點的位置
struct ArcNode *nextarc; //指向下一條弧的指針
}ArcNode; //弧結點
typedef struct{
ArcNode *AdjList[MaxVerNum]; //指向第一條依附該頂點的弧的指針
int vexnum,arcnum; //圖的當前頂點和弧數
int GraphKind; //圖的種類,無向圖-0,有向圖-1
}Graph;
typedef struct //隊列的結構體
{
int elem[MaxSize]; //數據域
int front,rear; //隊頭,隊尾指針
}SeQueue; //
Bool visited[MaxVerNum]; //全局變量--訪問標志數組
void Create_Graph(Graph *G)
{
int i,start,end;
ArcNode *s;
for(i=1;i<=(*G).vexnum;i++)
(*G).AdjList[i]=NULL; //初始化指針數組
for(i=1;i<=(*G).arcnum;i++)
{
scanf("%d%d",&start,&end); //輸入弧的起點和終點
s=(ArcNode *)malloc(sizeof(ArcNode)); //生成一個弧結點
s->nextarc=(*G).AdjList[start];
s->adjvex=end;
(*G).AdjList[start]=s;
if((*G).GraphKind==0) //若是無向圖,再插入到終點的弧鏈中
{
s=(ArcNode *)malloc(sizeof(ArcNode));
s->nextarc=(*G).AdjList[end];
s->adjvex=start;
(*G).AdjList[end]=s;
}
}
}
int First_AdjVex(Graph G,int v) //找第vi個頂點的第一個鄰接頂點
{
if(!G.AdjList[v])
return 0;
else
return (G.AdjList[v]->adjvex);
}
int Next_AdjVex(Graph G,int v,int u) //找第vi個頂點相對u的下一個鄰接頂點
{
ArcNode *p;
p=G.AdjList[v];
while(p->adjvex!=u) //在頂點vi的弧鏈中找到頂點u
p=p->nextarc;
if(p->nextarc==NULL) //若已是最后一個頂點,返回0
return 0;
else
return (p->nextarc->adjvex); //返回下一個鄰接頂點的序號
}
void Init_Queue(SeQueue *Q)
{
(*Q).front=(*Q).rear; //初始化隊列
}
Bool Empty_Queue(SeQueue Q) //判斷隊列是否為空
{
if(Q.front==Q.rear)
return True;
else
return False;
}
Bool In_Queue(SeQueue *Q,int ch)//入隊操作,成功True
{
if(((*Q).rear+1)%MaxSize==(*Q).front)
return False;
(*Q).elem[(*Q).rear]=ch;
(*Q).rear=((*Q).rear+1)%MaxSize;
return True;
}
Bool Out_Queue(SeQueue *Q,int *ch)//出隊操作,成功True
{
if((*Q).front==(*Q).rear)
return False;
(*ch)=(*Q).elem[(*Q).front];
(*Q).front=((*Q).front+1)%MaxSize;
return True;
}
void DFS(Graph G,int i) //從第i個頂點出發遞歸的深度遍歷圖
{
int w;
visited[i]=True; //訪問第i個頂點
printf("%d->",i);
for(w=First_AdjVex(G,i);w;w=Next_AdjVex(G, i, w))
if(!visited[w])
DFS(G,w); //對尚未訪問的鄰接頂點w調用DFS
}
void DFS_Traverse(Graph G) //深度優先遍歷算法
{
int i;
printf("深度優先遍歷:");
for(i=1;i<G.vexnum;i++)
visited[i]=False; //訪問標志數組初始化
for(i=1;i<G.vexnum;i++)
if(!visited[i])
DFS(G,i);
printf("\b\b \n");
}
//廣度優先遍歷,非遞歸,輔助隊列Q和訪問櫝志數組visited
void BFS_Traverse(Graph G)
{
int i,u,w;
SeQueue Q;
printf("廣度優先遍歷:");
for(i=1;i<=G.vexnum;i++)
visited[i]=False; //訪問標志數組初始化
Init_Queue(&Q); //初始化隊列
for(i=1;i<=G.vexnum;i++)
if(!visited[i])
{
visited[i]=True; //訪問頂點vi
printf("%d->",i);
In_Queue(&Q, i); //將序號i入隊
while(!Empty_Queue(Q)) //若隊列不空,繼續
{
Out_Queue(&Q, &u);//將隊首元素出隊並置u
for(w=First_AdjVex(G, u);w;w=Next_AdjVex(G, u, w))
if(!visited[w]) //對u的尚未訪問的鄰接頂點w進行訪問並入隊列
{
visited[w]=True;
printf("%d->",w);
In_Queue(&Q, w);
}
}
}
printf("\b\b \n");
}
int main(int argc, const char * argv[]) {
Graph G;
char j='y';
//system("cls");
while(j!='N' && j!='n')
{
printf("輸入0或1(無向圖-0,有向圖-1):");
scanf("%d",&G.GraphKind);
printf("(如:4,3)輸入頂點數和弧數:\n");
scanf("%d%d",&G.vexnum,&G.arcnum);
printf("如:1,2\n1,3\n輸入各邊弧尾和弧頭:\n");
Create_Graph(&G);
DFS_Traverse(G);
BFS_Traverse(G);
printf("圖的遍歷完畢,繼續進行嗎?(Y/N)");
scanf("%c",&j);
}
return 0;
}
無向圖運行結果:
有向圖運行結果: