繁体   English   中英

使用BFS算法找到最短路径

[英]Using BFS algorithm to find the shortest path

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

用于查找最短路径 (用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&Felix的启发,来自: 竞争编程3

不,您不必在代码中进行太多更改。 如果使用Queue将DFS替换为replace stack,它将变为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”方面有所不同。

希望这可以帮助 !

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM