1.前言
本篇文章是在认识图的基础上进行叙述的,如果你还不知道什么是图,图的存储结构。那么请你先阅读以下文章。
本章重点:
本篇主要讲解及模拟实现图的遍历算法--DFS和BFS,以及最小生成树算法Kruskal和Prim算法。
2.什么是图的遍历
图的遍历就是,从任意一个顶点开始,可以通过某种方式走过所有的顶点,这就叫做图的遍历。
那么图可以用什么方法来进行遍历呢?之前二叉树的遍历可以通过递归的办法和层序遍历的方法来获取结果,请思考那么图是否也可以使用这种方法呢?---答案是可以的。这就是DFS和BFS
2.1 图的广度优先遍历
先解释什么叫做广度优先遍历:简单来说就是先把一个顶点的相邻朋友顶点全部走完。
例子如下:
比如现在要找东西,假设有三个抽屉,东西在那个抽屉不清楚,现在要将其找到,广度优先遍历的做法是:
- 先将三个抽屉打开,在最外层找一遍
- 将每个抽屉中红色的盒子打开,再找一遍
- 将红色盒子中绿色盒子打开,再找一遍直到找完所有的盒子
注意:每个盒子只能找一次,不能重复找
转换到图上面那就是如下情形
模拟一遍过程
假设以A顶点为源点开始遍历,对于顶点A来说, 先走B,C,D. 然后再看B顶点, 走A,C,E, 但是A和C已经走过了,所以不能再此将它们算进去. --那么用什么方法来记录他们是否走过呢?做法很简单, 使用一个visited数组, 数组用来存储一个顶点是否已经入过队列了.
那用什么容器来临时存储这些值呢?--很明显用队列,因为你把A放进容器之后,要判断A的朋友是哪些,然后把A拿出容器,这就联想到了先进先出的情形,所以采用队列这个容器
细节把握清楚了,那么写出代码来就不是很大的问题了。直接上代码
void BFS(const V& src)//广度优先遍历
{
int srci = GetIndex(src);
if (srci == -1) return;
vector<bool> visited(_ver.size(), false);
queue<int> que;
que.push(srci);
visited[srci] = true;
cout << _ver[srci] << " ";
while (!que.empty())
{
int front = que.front();
que.pop();
for (int i = 0; i < _ver.size(); ++i)
{
if (_martix[front][i] != int_MAX && visited[i] == false)
{
que.push(i);
visited[i] = true;
cout << _ver[i] << " ";
}
}
}
cout << endl;
}
注意:这个代码要和前面的初始图论里面的代码结合起来看,这是在邻接矩阵里面实现的。
2.2 图的深度优先遍历
图的优先遍历就是一条路走到黑,走不通再回退
例子如下:
比如现在要找东西,假设有三个抽屉,东西在那个抽屉不清楚