在实现队列的代码之后,经过调整,开始着手实现广搜BFS
我们从上篇文章数据结构(图)的代码实现和测试(1)——邻接矩阵实现和DFS之后开始说明
我们对图的遍历函数进行一些小小的改动,主要将最后测试的DFS改为BFS
void graphTraverse(Graph& G)
{
int v;
QueueA<int> Q;
for (int v = 0; v < G.n(); v++) //预处理,将所有节点全部设置为未放问的状态,准备遍历
{
G.setMark(v, UNVISITED);
}
for (int v = 0; v < G.n(); v++)/*其实是从v = 0的顶点开始遍历,但是for循环的目的是为了检验是否遍历了所有的顶点
如果有顶点没有被访问,则从这个顶点开始继续进行深度优先遍历
*/
{
if (G.getMark(v) == UNVISITED)
{
std::cout << v << std::endl;//该打印语句用于测试
BFS(G,v,&Q); //这个位置可以放 任意 遍历的算法,不只是DFS BFS也可以
//DFS(G,v);
}
}
}
之后来看BFS的实现
void BFS(Graph& G, int start,Queue<int> *Q)
{
int v, w;
Q->enqueue(start); //从start节点开始遍历,先将start节点入队
G.setMark(start, VISITED);//访问start节点并将其标记为已访问
while (Q->length()!=0)
{
v = Q->dequeue(); //如果队列不为空,取一个队首的元素
/*
这里可以放privisit(G,v)函数,以便对访问的v节点进行处理
*/
std::cout << v << std::endl; //用来检查bfs的路径
for (int w = G.first(v); w < G.n(); w = G.next(v,w))//从这个v节点开始,遍历访问他的所有子节点
{
if (G.getMark(w) == UNVISITED )
{
G.setMark(w, VISITED);
Q->enqueue(w); //将访问的所有子节点放到队尾,以便最后处理
}
}
}
}
我依旧按照教材中的图来测试
下面来看测试代码
test.cpp
#include"Need.h"
int main() {
Graphm A(6); //创建一个6个节点的图
A.setEdge_undirected(0, 2, 2);
A.setEdge_undirected(0, 4, 5);
A.setEdge_undirected(4, 5, 5);
A.setEdge_undirected(2, 3, 2);
A.setEdge_undirected(3, 5, 1);
A.setEdge_undirected(2, 5, 4);
A.setEdge_undirected(5, 1, 5);
A.setEdge_undirected(1, 2, 3);
A.print();
graphTraverse(A);
//int d[6];
//Dijkstra(&A, d, 0);
//std::cout << std::endl;
//printDijkstra(A, d);
return 0;
}
另外需要注意的是,在这里我写了一个新的函数:setEdge_undirected();
这个函数是为了弥补原来的setEdge函数只能一条一条添加有向边 导致效率低下的缺点
setEdge_undirected函数可以直接在两个顶点之间添加无向边
下面是setEdge_undirected函数的实现
void Graphm::setEdge_undirected(int v1, int v2, int wt)
{
Assert(wt > 0, "非法的权值");
if (matrix[v1][v2] == 0 && matrix[v2][v1]==0)
{
numEdge++;
}
matrix[v1][v2] = wt;
matrix[v2][v1] = wt;
}
测试结果如下
代表从0 2 4 1 3 5的路径进行BFS遍历