图的广度优先遍历(邻接矩阵)
广度优先遍历算法思想:
借助队列,先将第一个顶点入队,每次顶点出队的时候,打印输出该顶点,然后再遍历邻接矩阵,把与该顶点所在行的所有不为0的纵坐标入队,如此重复直到所有的顶点都出队,这样对邻接矩阵存储的图的广度优先遍历就遍历完毕了。
测试数据:
8 10
1 2 3 4 5 6 7 8
1 2
1 5
2 6
3 6
3 7
3 4
4 7
4 8
6 7
7 8
#include<iostream>
#include<malloc.h>
using namespace std; //vertex:顶点 arc:弧 adjacent:邻近的
#define MaxVertexNum 100
typedef char VertexType; //顶点的数据类型
typedef int EdgeType; //边的数据类型
typedef struct{
VertexType Vex[MaxVertexNum]; //定点表
EdgeType Edge[MaxVertexNum][MaxVertexNum]; //邻接矩阵,边表
int vernum,arcnum; //图的当前顶点数和弧数
}MGraph; //适合存储稠密图
//队、队结点的存储结构
typedef struct LinkNode{
int data;
struct LinkNode *next;
}LinkNode;
typedef struct {
LinkNode *front,*rear;
}LinkQueue,*PLinkQueue;
//初始化队列
void InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));//头指针和尾指针指向同一节点,该节点无内容
Q.front->next=NULL;
Q.rear->next=NULL;
}
//判队空
bool EmptyQueue(LinkQueue Q)
{
if(Q.front==Q.rear)
return true;
else
return false;
}
//入队
void EnQueue(LinkQueue &Q,int x)
{
LinkNode *S=(LinkNode*)malloc(sizeof(LinkNode));
S->data=x;
S->next=NULL;
Q.rear->next=S;
Q.rear=S;
}
//出队
bool DeQueue(LinkQueue &Q,int &T)
{
if(EmptyQueue(Q))
return false;
LinkNode *p=Q.front->next;
T=p->data;
Q.front->next=p->next;
if(Q.rear==p)//出队前只有一个结点,出队后变成空
Q.rear=Q.front;
free(p);
return true;
}
//邻接矩阵法创建一个图
void CreateMGraph(MGraph *G)
{
int i,j,k,w;
printf("请输入图的顶点数和边数:");
cin>>G->vernum>>G->arcnum;
printf("请输入图的各个顶点的信息(A,B…):");
for(i=1;i<=G->vernum;i++)
cin>>G->Vex[i];//"%c"中%c后面要有空格
for(i=1;i<=G->vernum;i++)
{
for(j=1;j<=G->vernum;j++)
G->Edge[i][j]=0;
}
printf("请输入各条边的信息(例:1 2表示在A顶点和B顶点之间有一条边):\n");
for(k=1;k<=G->arcnum;k++)
{//此为创建有向图的邻接矩阵
int Iindex,Jindex;
cin>>Iindex>>Jindex;
G->Edge[Iindex][Jindex]=1;
//如果加上G->Edge[j][i]=1;则建立的是无向图的邻接矩阵
G->Edge[Jindex][Iindex]=1;
}
}
//打印邻接矩阵
void DisplayMGraph(MGraph G)
{
int i,j;
printf(" ");
for(i=1;i<=G.vernum;i++)
printf("%c ",G.Vex[i]);
for(i=1;i<=G.vernum;i++)
{
printf("\n%c\t",G.Vex[i]);
for(j=1;j<=G.vernum;j++)
printf("%d ",G.Edge[i][j]);
}
}
bool Visited[MaxVertexNum];//记录结点是否被访问过
LinkQueue Q;
int FirstNeighbor(MGraph G,int x)
{
int k;
for(k=1;k<=G.vernum;k++)
{
if(G.Edge[x][k]==1)
break;
}
if(k<=G.vernum)
return k;
else
return -1;
}
int NextNeighbor(MGraph G,int x,int y)
{
int j;
for(j=y+1;j<=G.vernum;j++)
{
if(G.Edge[x][j]==1)
break;
}
if(j<=G.vernum)
return j;
else
return -1;
}
void BFS(MGraph G,int v)
{
printf("%c ",G.Vex[v]);
Visited[v]=true;
EnQueue(Q,v);
while(!EmptyQueue(Q))
{
int i;
DeQueue(Q,v);
for(i=FirstNeighbor(G,v);i>=0;i=NextNeighbor(G,v,i))
{
if(!Visited[i])
{
printf("%c ",G.Vex[i]);
Visited[i]=true;
EnQueue(Q,i);
}
}
}
}
void BFSTraverse(MGraph G)//breadth first search 广度优先遍历
{//算法思想:类似于树的层序遍历,创建一个队列,入队,当队空时,
//图遍历完毕。
int i;
InitQueue(Q);
for(i=1;i<=G.vernum;i++)
Visited[i]=false;
for(i=1;i<=G.vernum;i++)
{
if(!Visited[i])
BFS(G,i);
}
}
int main()
{
MGraph G;
CreateMGraph(&G);
DisplayMGraph(G);
printf("\n从顶点1开始的图的深度优先遍历序列为:");
BFSTraverse(G);
return 0;
}