在上一篇文章中,笔者介绍了DFS,这篇文章介绍的是图论的另一个经典算法--BFS(广度优先搜索算法)。
这一篇文章将对BFS作出介绍。队列的push操作将元素添加到队列的末尾,但pop操作将队列的第一个元素弹出,这与堆栈有差异。
我们构造这样一个图(如图1),并通过C++实现BFS,本文处理的图比二叉树要更复杂,如果时针对二叉树的BFS,程序会更为简单
算法过程:
1.将根节点放入队列中
2.从队列中取出第一个元素,将队列中的第一个元素弹出
3.将所取得元素的全部节点加入队列中
4.判断队列是否为空
a. 若是,则结束
b.若不是,则跳到第二步
以下代码在vs2017中通过编译
//利用C++实现广度优先搜索算法,如有疑问请联系
//作者:cclplus 邮箱:707101557@qq.com
//或者在评论区下方提问
//如果你认为打赏作者是有必要的,我的支付宝账号也是707101557@qq.com
#include<iostream>
#include<vector>
#include<queue>
#include<memory.h>
using namespace std;
vector<vector<int>> tree;//声明一个二维向量
int flag[10];//用于搜索到了节点i的第几个节点
queue<int> M;//声明一个队列
int ar_tree[8] = { 1,1,1,3,5,3,5,7 };
void BFS(int node) {
int temp;
cout << node << " ";
//从队列中取出第一个节点
int m_first = M.front();
M.pop();
while(flag[node] < tree[node].size()) {
temp = tree[node][flag[node]];
flag[node]++;
//把temp加入队列中
M.push(temp);
}
if (!M.empty()) {
BFS(M.front());
}
}
int main() {
ios::sync_with_stdio(false);
memset(flag, 0, sizeof(flag));
int i,temp;
tree.resize(10);//图中的数共有九个节点
//生成树
for (i = 2; i <=9; i++) {
temp = ar_tree[i - 2];
tree[temp].push_back(i);//表示第i个节点为第temp个节点的子节点
}
//BFS
cout << "BFS过程:" << endl;
M.push(1);
BFS(1);
cout << endl;
return 0;
}
运行结果:
队列和递归同时使用并不是一个明智的做法(这样做会大大降低程序的可读性),下面开始解决这个问题,这一次不再使用递归
/*
*作者:cclplus
*写作时间:2018/12/23
*/
#include <iostream>
#include <queue>
using namespace std;
class tree{
public:
int num;
tree * left = nullptr;
tree * middle = nullptr;
tree * right = nullptr;
tree(int m) :num(m) {//构造函数
left = nullptr;
middle = nullptr;
right = nullptr;
}
tree() :num(0) {//构造函数
left = nullptr;
middle = nullptr;
right = nullptr;
}
~tree() {}//析构函数
};
queue<tree *> ccl;//声明一个队列,用于存储树的节点
tree mytree[10];
int ar_tree[8] = { 1,1,1,3,5,3,5,7 };
tree * tree_ptr;
int main() {
ios::sync_with_stdio(false);
mytree[1] = tree(1);
for (int i = 2; i <= 9; i++) {
mytree[i] = tree(i);//重新构造
tree_ptr= &mytree[ar_tree[i - 2]];
if (tree_ptr->left == nullptr) {
tree_ptr->left = &mytree[i];
}
else{
if (tree_ptr->middle== nullptr) {
tree_ptr->middle = &mytree[i];
}
else {
tree_ptr->right= &mytree[i];
}
}
}
//把根节点放入队列中
ccl.push(&mytree[1]);
while (!ccl.empty()) {//当队列不为空时,程序运行
tree_ptr = ccl.front();//读取节点
//cout << tree_ptr->num << endl;
if (tree_ptr->left != nullptr) {
ccl.push(tree_ptr->left);
}
if (tree_ptr->middle != nullptr) {
ccl.push(tree_ptr->middle);
}
if (tree_ptr->right != nullptr) {
ccl.push(tree_ptr->right);
}
cout << tree_ptr->num << " ";
ccl.pop();
}
cout << endl;
return 0;
}
笔者更推荐使用数据结构树的这份代码,数据结构让程序边得更加清晰明了。