如何实现广度优先搜索?

时间:2017-10-21 10:03:45

标签: c++ algorithm breadth-first-search

我试图在C ++中实现BFS,该函数应该像这样工作:取一个图形&一个顶点作为参数,然后创建两个向量,其中一个用于存储与参数顶点相邻的顶点,然后检查这些顶点,如果其中一个未被访问,则获取它的邻接并将它们添加到向量,之后顶点应标记为VISITED并打印;我写了这段代码,但确实输出了任何内容。注意:我确保其他功能&像图这样的数据结构正在工作,问题在于BFS功能,我希望你们中的一些人可以帮我修复它。

 #include <iostream>
 #include <vector>
 #include <queue>

 using namespace std;

 enum Mark {VISITED, UNVISITED};

 struct Vertex {

   char name;
   Mark mark;
};

struct Edge{

   Vertex v1;
   Vertex v2;
   Edge(Vertex vertex1, Vertex vertex2): v1(vertex1), v2(vertex2){};
};

 struct Graph{

vector<Vertex>vertices;
vector<Edge>edges;

vector<pair<Vertex, Edge>> adjacent(char u){

    vector<pair<Vertex, Edge>>res;

    for(Edge e : edges){
        if(e.v1.name == u){
            res.push_back(make_pair(e.v2, e));
        }else if(e.v2.name == u){
            res.push_back(make_pair(e.v1, e));
        }
    }
    return res;
}

 vector<Vertex> getAdj(char u){

    vector<Vertex>result;

    for(Edge e: edges){
        if(e.v1.name == u){
            result.push_back(e.v2);
        }else if(e.v2.name == u){
            result.push_back(e.v1);
    }
}
    return result;
}
};

void BFS(Graph g, Vertex u){

    vector<Vertex>vec = g.getAdj(u.name);

    for(Vertex v : vec){
       if(v.mark == UNVISITED){
           vector<Vertex>q = g.getAdj(v.name);
             for(int i=0; i<q.size(); i++){
                vec.push_back(q[i]);
             }
          v.mark = VISITED;
          vec.pop_back();
          cout << v.name << " ";
    }
  }
}





int main(int argc, const char * argv[]) {

  Graph g;

  Vertex v1, v2, v3, v4, v5, v6;

   v1.name = 'A';
   v2.name = 'B';
   v3.name = 'C';
   v4.name = 'D';
   v5.name = 'E';
   v6.name = 'Z';

   g.edges.push_back(Edge(v1, v2));
   g.edges.push_back(Edge(v1, v3));
   g.edges.push_back(Edge(v2, v3));
   g.edges.push_back(Edge(v2, v4));
   g.edges.push_back(Edge(v3, v4));
   g.edges.push_back(Edge(v3, v5));
   g.edges.push_back(Edge(v4, v5));
   g.edges.push_back(Edge(v4, v6));
   g.edges.push_back(Edge(v5, v6));

   BFS(g, v1);

   cout << endl;

  }

1 个答案:

答案 0 :(得分:0)

您尚未完全初始化Vertex。您为他们命名,但不是最初的mark标记。

您可以在主要内容中添加:

   v1.mark = UNVISITED;
   v2.mark = UNVISITED;
   v3.mark = UNVISITED;
   v4.mark = UNVISITED;
   v5.mark = UNVISITED;
   v6.mark = UNVISITED;

你也可以做这样的事情(用enum class代替可能更好):

 enum Mark {VISITED, UNVISITED};

 struct Vertex {

   char name;
   Mark mark = UNVISITED;
};

(我还会创建一个构造函数来初始化名称,以确保你不会忘记这样做。)

<强> 更新:

您的BFS有几个问题:   - 由于你在内循环中向vec添加元素,外循环不能正常工作(我认为它与迭代器有关,因为你改变了向量的大小而发生了时间)。我设法使用常规for循环来解决它。

  • 即使你设法使用了一个远程for-loop,你也可以从&#34;从左到右&#34;在向量中。并且你正在使用pop_back()从向量的末尾删除(所以在向量的最右边)。我不认为这就是你想要的。

  • 通过将eeher Vertex标记为已访问且未访问,您有正确的想法。但是,您只需更新Vertex功能vecBFS的{​​{1}}。但它们只是来自getADj方法的副本,这意味着每次将新邻居添加到vec时,只要有已经访问过的顶点,该值就不可知。实际上,您正在添加一个从未访问过的新Vertex

可能还有其他问题,但已经有了这些问题,你应该掌握很多东西!

我建议您使用调试器和/或像valgrind&#39;这样的工具来帮助查找代码中的问题。