使用BFS算法寻找最短路径

Using BFS algorithm to find the shortest path

本文关键字:最短路径 寻找 算法 BFS 使用      更新时间:2023-10-16
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 -辅助变量

DFS和BFS本质上是相同的算法。关键在于您使用哪种数据结构,或者更确切地说,是首先探索哪个节点。

深度优先搜索利用堆栈,因此在返回算法之前会尽可能地向下搜索。

要利用广度优先搜索,您需要使用节点队列,并探索每个节点,将它们的邻居(如果尚未访问过)添加到队列中,然后在继续之前处理父节点的其余邻居。

这不会对你的代码有很大的改变,只是改变了你从列表中获取节点的方式。

您可以简单地使用q.pop_front()来获取您的节点,而不是弹出后面。

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

For Finding最短路径 (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];
}

灵感来自Steven &费利克斯:竞技节目3

不,您不必在代码中更改太多。

将DFS中的replace stack替换为Queue,它将变成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的使用上"不同。