题目描述
广度优先搜索遍历类似于树的按层次遍历的过程。其过程为:假设从图中的某顶点v出发,在访问了v之后依次访问v的各个未曾被访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作为起始点。重复上述过程,直至图中所有顶点都被访问到为止。
其算法可以描述如下:
在本题中,读入一个无向图的邻接矩阵(即数组表示),建立无向图并按照以上描述中的算法遍历所有顶点,输出遍历顶点的顺序。
输入
输入的第一行包含一个正整数n,表示图中共有n个顶点。其中n不超过50。
以后的n行中每行有n个用空格隔开的整数0或1,对于第i行的第j个0或1,1表示第i个顶点和第j个顶点有直接连接,0表示没有直接连接。当i和j相等的时候,保证对应的整数为0。
输入保证邻接矩阵为对称矩阵,即输入的图一定是无向图。
输出
只有一行,包含n个整数,表示按照题目描述中的广度优先遍历算法遍历整个图的访问顶点顺序。每个整数后输出一个空格,并请注意行尾输出换行。
样例输出
4 0 0 0 1 0 0 1 1 0 1 0 1 1 1 1 0
样例输出
0 3 1 2
完整代码
#include <iostream>
#include <iomanip>
#include <cstdio>
using namespace std;
#define MAXQSIZE 100
#define ERROR 0
#define OK 1
#define MVNum 100 //最大顶点数
typedef string VerTexType; //假设顶点的数据类型为字符串
typedef int ArcType; //假设边的权值类型为整型
bool visited[MVNum];
typedef int Status ;
typedef int QElemType;
//建立队列
typedef struct {
QElemType* base;//初始化时动态分配存储空间
int front;//头指针
int rear;//尾指针
} SqQueue;
// 循环队列的初始化
Status InitQueue(SqQueue& q) //构造一个空队列Q
{
q.base = new QElemType[MAXQSIZE]; //为队列分配一个最大容量为MAXSIZE的数组空间
q.front = q.rear = 0; //头指针和尾指针置为零,队列为空
return OK;
}
void DestroyQueue(SqQueue& q)
{
/* 销毁队列Q,Q不再存在 */
if (q.base)
delete[]q.base;
q.base = NULL;
q.front = q.rear = 0;
}
bool QueueEmpty(SqQueue q)
{
/****在此下面完成代码***************/
if (q.rear == q.front)
return OK;
else
return ERROR;
/***********************************/
}
Status EnQueue(SqQueue& q, QElemType e) //插入元素e为Q的新的队尾元素
{
/****在此下面完成代码***************/
if ((q.rear + 1) % MAXQSIZE == q.front)
return ERROR;
q.base[q.rear] = e;
q.rear = (q.rear + 1) % MAXQSIZE;
return OK;
/***********************************/
}
//算法3.14 循环队列的出队
Status DeQueue(SqQueue& q, QElemType& e) //删除Q的队头元素,用e返回其值
{
/****在此下面完成代码***************/
if (q.front == q.rear)return ERROR;
e = q.base[q.front];
q.front = (q.front + 1) % MAXQSIZE;
return OK;
/***********************************/
}
//------------图的邻接矩阵------------------
typedef struct {
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum, arcnum; //图的当前点数和边数
} Graph;
//得到顶点i的数据
VerTexType Vertexdata(const Graph& g, int i)
{
return g.vexs[i];
}
int LocateVex(const Graph& g, VerTexType v)
{
//确定点v在G中的位置
for (int i = 0; i < g.vexnum; ++i)
if (g.vexs[i] == v)
return i;
return -1;
}//LocateVex
int FirstAdjVex(const Graph& g, int v)
{
//返回v的第一个邻接点编号,没有返回-1
/****在此下面完成代码***************/
int j;
for (j = 0; j < g.vexnum; j++)
if (g.arcs[v][j] == 1)
return j;
return -1;
/***********************************/
}//FirstAdjVex
int NextAdjVex(const Graph& g, int v, int w)
{
//返回v相对于w的下一个邻接点,没有返回-1
/****在此下面完成代码***************/
int i;
for (i = w + 1; i < g.vexnum; i++)
{
if (g.arcs[v][i] == 1)
return i;
}
return -1;
/***********************************/
}//NextAdjVex
void BFS(Graph g, int v)
{
cout << v << " "; SqQueue q; int u;//访问第v个顶点,标志数组相应的分量值为true
visited[v] = true;
InitQueue(q);
EnQueue(q, v);//v入队
while (!QueueEmpty(q))//队列非空
{
DeQueue(q, u);队头元素出队并置为u
for(int w=FirstAdjVex(g,u);w>=0;w=NextAdjVex(g,u,w))//依次检查u的所有邻接点w
if (!visited[w])//w为u未访问的邻接顶点
{
cout << w<<' '; visited[w] = true;
EnQueue(q, w);
}
}
}
void CreateUDG(Graph& g)
{
//采用邻接矩阵表示法,创建无向图G
/****在此下面完成代码***************/
cin >> g.vexnum;
for (int i = 0; i < g.vexnum; i++)
{
for (int j = 0; j < g.vexnum; j++)
{
cin >> g.arcs[i][j];
}
}
/***********************************/
}//CreateUDN
void DestroyUDG(Graph& g)
{
//you should do this
g.arcnum = g.vexnum = 0;
}
int main()
{
Graph g;
CreateUDG(g);
BFS(g, 0);
DestroyUDG(g);
return 0;
}//main