std::list <int> q;
std::vector<bool> visited(cols + 1);
for(int i = 1; i <= cols; i++) visited[i] = false;
visited[x] = true;
if(!l[x].empty())
{
for(std::list<int>::iterator i = l[x].begin(); i != l[x].end(); i++)
{
q.push_back(x); q.push_back(* i);
}
while(!q.empty())
{
y = q.back(); q.pop_back();
x = q.back(); q.pop_back();
if(!visited[y])
{
visited[y] = true;
if(!l[y].empty())
for(std::list<int>::iterator i = l[y].begin(); i != l[y].end(); i++)
{
if(!visited[*i])
{q.push_back(y); q.push_back(* i);}
}
dfst[x].push_back(y);
if(flag != 0) dfst[y].push_back(x);
}
}
}
这是我在图中查找生成树的DFS算法。我需要将它转换为BFS算法,找到两个顶点之间的最短路径。嗯......我怎么能这样做? BFS算法有点类似于上面的那个吗?或者我是否需要从头开始编写它?
l - 邻接清单 dfst - 最后持有生成树的数组 x - 起始顶点 y - 辅助变量
答案 0 :(得分:3)
DFS和BFS本质上是相同的算法。诀窍在于您使用的数据结构,或者您首先要探索的节点。
深度优先搜索使用堆栈,因此在返回算法之前会尽可能地向下移动。
要利用广度优先搜索,您需要使用节点队列,并探索每个节点,将其邻居(如果尚未访问)添加到队列中,然后处理父节点的其余邻居,然后再继续起。
这不会对您的代码进行大幅改动,只会改变您从列表中获取节点的方式。
不要弹出背面,而只需使用q.pop_front()
来获取节点。
答案 1 :(得分:3)
BFS与DFS类似。您可以查看深度为1的所有节点,然后查看深度为2的所有节点,直到您访问所有节点,而不是尽可能深入地进行回溯和重复。
基本算法:
-Choose a starting node and add to LookQueue
-look at all nodes directly touching and add them to LookQueue
-when you've looked at them all
-look at all nodes in LookQueue (removing them as you do)
and look at all nodes touching them (adding them as you do)
-repeat until all nodes are visited
答案 2 :(得分:2)
寻找最短路径 (用C ++ / C ++ 11编写)
我认为这一点非常重要,特别是因为标题位于最短路径上!(下面的代码实际上允许您找到一个) 此外: 如上所述(在第二个回复的评论中)DFS和BFS几乎不是(!)相同的算法,代码中的相似性,其中用队列替换堆栈并允许您从一个跳转到另一个不使它们“基本相同”。到目前为止,BFS是在未加权图中找到最短路径的更好/正确的(在两者之间)。 BFS正在从源头构建图层,而DFS正在尽可能深入。
实际上在运行BFS(找到最短路径)时,您应该使用带有非常大数字的“距离”参数初始化节点,而使用访问过的DS,将其更新为父距离+ 1(仅当它是仍然具有初始化值。)
简单示例如下:
#include <iostream>
#include <vector>
#include <queue>
#include <limits>
using namespace std;
const int imax = std::numeric_limits<int>::max();
using vi = vector<int>;
/* printPath - implementation at the end */
void
printPath(int s, int t, const vi &path);
/*input:
* n is number of the nodes in the Graph
* adjList holds a neighbors vector for each Node
* s is the source node
*/
void dfs(int n, vector<vi> adjList, int s)
{
//imax declared above as the max value for int (in C++)
vector<int> distance(n, imax);
vi path;
queue<int> q; q.push(s); distance[s] = 0;
while (!q.empty()) {
auto curr = q.front(); q.pop();
for (int i = 0; i < (int)adjList[curr].size(); ++i) {
if (distance[i] == imax) {
distance[i] = distance[curr] + 1;
//save the parent to have the path at the end of the algo.
path[i] = curr;
}
}//for
}//while
/* t can be anything you want */
int t = 5;
printPath(s, t, path); cout << endl;
}
/* print the shortest path from s to t */
void
printPath(int s, int t, const vi &path)
{
if (t == s) {
return;
}
printPath(s, path[t], path);
cout << path[t];
}
受史蒂文&amp; amp; Felix,来自: Competitive Programming 3
答案 3 :(得分:0)
不,您不必在代码中进行太多更改。只需在带有队列的DFS的情况下替换替换堆栈,它将成为BFS。
BFS和DFS的实现差异在于“BFS是使用Queue实现的,而DFS正在使用Stack”(原因很明显,DFS在迷宫中的确如此深度。)
自己看看变化:
DFS:
void dfs(int start)
{
int j,temp;
stack<int> s; //STACK
s.push(start);
vector<int>:: iterator it;
while(s.empty()==0)
{
temp=s.top(); // Top element from Stack
s.pop();
status[temp]=1; // marked as visited , 0 means unvisited
cout<<temp<<endl; // visited element
for(it=list[temp].begin();it!=list[temp].end();it++)
{
j=*it;
if(status[j]==0)
{
s.push(j);
status[j]=2; // means that it is in stack
}
}
}
}
BFS:
void bfs(int start)
{
int j,temp;
queue<int> q; // QUEUE
q.push(start);
vector<int>:: iterator it;
while(q.empty()==0)
{
temp=q.front(); // Front element from Queue
q.pop();
status[temp]=1; // marked as visited , 0 means unvisited
cout<<temp<<endl; // visited element
for(it=list[temp].begin();it!=list[temp].end();it++)
{
j=*it;
if(status[j]==0)
{
q.push(j);
status[j]=2; // means that it is in queue
}
}
}
}
正如你所看到的,两者的实现只是“使用STACK和QUEUE”。
希望这有帮助!