dfs
作者:互联网
这里记录一下老师上课讲过的dfs.
主要思路是,我们对于每一个节点都设置白色、灰色和黑色三种颜色,分别表示三种状态:未访问、正在访问和访问完毕。这三种状态的标准是根据某一个具体节点的邻居节点来定的,就是说,对于某一个具体节点,如果还没有访问完该节点的所有邻居节点,那么就表示这个节点处于正在访问状态,如果所有邻居节点都访问完毕,那就表示这个节点已经访问完毕。
那么首先,为了简单起见,我们直接用一个二维数组来表示边,且在初始化的时候,所有节点到其他任何节点之间的距离都设置为无穷大,包括节点到它自己之间的距离。
1 void init() 2 { 3 for (int i = 1; i <= n; ++i) { 4 for (int j = 1; j <= n; ++j) { 5 edge[i][j] = INT_MAX; 6 } 7 } 8 }
然后,就可以开始dfs了。这个函数的参数只需要设置一个,表示当前正在访问的节点。首先,我们当然就是需要把这个节点的颜色设置为灰色啦!然后,我们开始访问它的所有邻居节点,一旦发现一个邻居节点并且这个邻居节点的颜色状态也是白色(表示未访问),那么就以这个邻居节点为基准,继续dfs.这就体现了深度的特点。等到全部访问完后,也就是这个节点的所有邻居节点都访问完毕了,那么就可以把这个节点的颜色设置为黑色了,最后就把它打印出来就可以了。
1 void dfs(int u) 2 { 3 color[u] = "grey"; 4 for (int j = 1; j <= n; ++j) { 5 if (edge[u][j] != INT_MAX && color[j] == "white") { 6 dfs(j); 7 } 8 } 9 color[u] = "black"; 10 cout << u << " "; 11 }
最后,为了防止访问的这个图是一个森林,我们还要来一个函数,遍历一遍这个图的所有节点,一旦发现有节点是白色的,那就访问。
void GraphTravel() { for (int i = 1; i <= n; ++i) { if (color[i] == "white") { dfs(i); } } }
最后来一波完整代码:
#include <iostream> #include <algorithm> #include <queue> #define N 100 using namespace std; queue<int> q; int edge[N][N]; string color[N]; int n, edges; void init() { for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { edge[i][j] = INT_MAX; } } } void dfs(int u) { color[u] = "grey"; for (int j = 1; j <= n; ++j) { if (edge[u][j] != INT_MAX && color[j] == "white") { dfs(j); } } color[u] = "black"; cout << u << " "; } void GraphTravel() { for (int i = 1; i <= n; ++i) { if (color[i] == "white") { dfs(i); } } } int main() { int start, end, weight; cout << "输入点的数量:" << endl; cin >> n; for (int i = 1; i <= n; ++i) { color[i] = "white"; } cout << "输入边的数量:" << endl; cin >> edges; cout << "依次输入起点、终点和边的权值:" << endl; init(); for (int i = 1; i <= edges; ++i) { cin >> start >> end >> weight; edge[start][end] = weight; edge[end][start] = weight; } GraphTravel(); return 0; }
再来一波运行效果:
对了,这个图长这样:
可能读者会对最后打印出来节点的顺序有所疑问,其实这是节点“变黑的顺序”,这个顺序很有用!具体有啥用呢?To be continued...
标签:int,void,dfs,访问,邻居,节点 来源: https://www.cnblogs.com/EvanTheGreat/p/15584764.html