#include <iostream>
#define MAXVEX 8 //起始顶点数默认为8,可在此直接修改
#define MAXEDGE 10 //起始边的数默认为10,可在此直接修改
using namespace std;
//该代码是无向图的邻接表的BFS
//注意点1:下标0的位置都不用,所以要多开辟一个空间
//注意点2:头结点信息既可以是字符A,B,C,D,也可以是字符'1','2'...
//注意点3:在创建邻接表时,使用头插法将边结点接在头结点之后
//将无向图的邻接表BFS改为有向图的邻接表BFS,则只要删去下面一段代码即可
//EdgeNode *s2 = new EdgeNode;
//s2->adjvex=m; //无向图现在n是头,m是尾
//s2->next = g.adjlist[n].firstedge;
//g.adjlist[n].firstedge=s2;
typedef struct EdgeNode
{
int adjvex;
struct EdgeNode *next;
}EdgeNode; //边结点
typedef struct
{
char vextexinfo; //存放头结点信息(如A,B,C,D)
EdgeNode *firstedge; //指向该结点的临边
}VextexNode,AdjList; //头结点(即邻接表)
typedef struct
{
int vexNum; //顶点数
int edgeNum; //边数
AdjList adjlist[MAXVEX+1]; //头结点数组
}ALGraph;
typedef struct
{
int *datas; //循环数组
int rear;
int head;
}Queue; //队列
/****************初始化队列***********************/
void Initqueue(Queue &q)
{
q.datas = new int[MAXVEX+1];
q.head = q.rear=0;
}
/****************队列的插入(入队列)***********************/
void Insertqueue(Queue &q , int e)
{
if((q.rear+1)%MAXVEX==q.head)
{
cout<<"队列已满!!!"<<endl;//实际此时还有一个空位
return;
}else
{
q.datas[q.rear] = e;
q.rear=(q.rear+1)%MAXVEX;
}
}
/****************队列的删除(出队列)***********************/
int Deletequeue(Queue &q)
{
int e;
e=q.datas[q.head];
q.head=(q.head+1)%MAXVEX;
return e;
}
/****************队列是否为空***********************/
int Emptyqueue(Queue &q)
{
if(q.rear==q.head)
return 0;
else
return 1;
}
/******************初始化邻接表*******************/
void InitAdjList(ALGraph &g)
{
g.vexNum=MAXVEX;
g.edgeNum=MAXEDGE;
//初始化头结点数组(即表头信息)
for(int i =1; i<=MAXVEX ; i++)
{
cout<<"请输入第"<<i<<"个结点的信息:";
cin>>g.adjlist[i].vextexinfo;
g.adjlist[i].firstedge=NULL; //初始化指针指向空
}
}
//通过两个结点来确认边,并得到这两个结点的在数组的下标位置
/*********************确定邻接表数组下标的位置*********************/
void Locata(ALGraph &g,char &vex1,char &vex2, int &m, int &n)
{
for(int i =1;i<=MAXVEX;i++)
{
if(vex1 == g.adjlist[i].vextexinfo)
m=i;
if(vex2 == g.adjlist[i].vextexinfo)
n=i;
}
}
/******************建立邻接表*******************/
void SetAdjList(ALGraph &g)
{
char vex1,vex2;
int m,n;
for(int i=1;i<=MAXEDGE;i++) //有几条边就循环几次
{
cout<<"请输入第"<<i<<"条边(形如A B,表示A到B的一条边)";
cin>>vex1>>vex2; //输入边的信息(即通过输入两顶点来确认边)
Locata(g,vex1,vex2,m,n);//得到vex1和vex2在邻接表的数组下标位置m和n
EdgeNode *s1 = new EdgeNode;
s1->adjvex=n; //无向图现在m是头,n是尾
s1->next = g.adjlist[m].firstedge;
g.adjlist[m].firstedge=s1;
//要是将其改为有向图的邻接表,则,下面这段代码全部删除
EdgeNode *s2 = new EdgeNode;
s2->adjvex=m; //无向图现在n是头,m是尾
s2->next = g.adjlist[n].firstedge;
g.adjlist[n].firstedge=s2;
}
}
/******************显示邻接表*******************/
void ShowAdjList(ALGraph &g)
{
cout<<"该图的邻接表如下:"<<endl;
for(int i=1;i<=g.vexNum ;i++)
{
EdgeNode *p;
cout<<"结点"<<i<<":";
for(p = g.adjlist[i].firstedge; p!=NULL ; p=p->next)
cout<<p->adjvex<<" ";
cout<<endl;
}
}
/*********************图的广度优先遍历BFS**************************/
void BFS(ALGraph &g ,int *visited, int v) //从vex这个结点开始深度遍历图
{
EdgeNode * p;
int u , w;
//创建队列
Queue q;
//初始化一个队列,队列长度为结点个数+1
Initqueue(q);
visited[v]=1;
//只要结点未被访问就访问后将其存进队列里面
Insertqueue(q,v);
while(Emptyqueue(q) != 0)
{
u=Deletequeue(q);
cout<<g.adjlist[u].vextexinfo<<"->"; //输出广度优先访问顺序
p=g.adjlist[u].firstedge;
while(p!=NULL) //p非空说明顶点u存在邻接点
{
w=p->adjvex;
if(visited[w] == 0) //说明w未被访问
{
visited[w]=1; //访问
Insertqueue(q,w); //进队列
}
p=p->next; //p指向顶点u的下一个邻接点
}
}
}
int main()
{
int visited[MAXVEX+1]={0}; //用来判断该结点是否被访问过,访问过为1,未访问则为0
int v = 1; //表明该图是从下标为1的结点开始广度优先遍历的
ALGraph g;
InitAdjList(g);
SetAdjList(g);
ShowAdjList(g);
BFS(g ,visited, v);
return 0;
}
C++数据结构-邻接表的图的广度优先遍历BFS
原文作者:数据结构之图
原文地址: https://blog.csdn.net/weixin_43323201/article/details/84748411
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/weixin_43323201/article/details/84748411
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。