如何使用stl迭代器和队列来实现图形的广度优先遍历?

问题描述

在概念上理解BFS的同时,我还没有掌握如何使用迭代器和队列来实现BFS。如果有人可以给我一些见解,以了解如何在我的代码中正确使用迭代器,我将非常感激。谢谢。

我什至在这里不确定迭代器是否是个好主意,我也尝试学习自动类型,但是我不确定如何使用它。

#ifndef GRAPH_H
#define GRAPH_H
#include<vector>
#include<iostream>
using namespace std;

struct vertex;

struct adjVertex{
    vertex *v;
};

struct vertex{

    string name;
    bool visited = false;
    int distance = 0;
    vector<adjVertex> adj;
};

class Graph
{
    public:
        void addEdge(string v1,string v2);
        void addVertex(string name);
        void displayEdges();
        void breadthFirstTraverse(string sourceVertex);
        int getConnectedBuildings();


    private:
        vector<vertex*> vertices;
};

#endif // GRAPH_H
void Graph::breadthFirstTraverse(string sourceVertex){
    
    //first initialize everything as not found
    for(int i = 0; i < vertices.size(); i++)
    {
        vertices[i]->visited = false;
    }

    //pointer to sourceVertex
    vertex *vstart;

    for(int i=0; i < vertices.size(); i++)
    {
        if(vertices[i]->name == sourceVertex){
            vstart = vertices[i];
            cout << "Starting vertex (root): " << vstart->name << " -> " << endl;
        }
    }
    
    queue<vertex*> q;
    
    vstart->visited = true;

    q.push(vstart);

    vertex *n;

    vector<int>:: iterator i;
    
    while(!q.empty()){
        n = q.front();

        q.pop();

        for(i = n->adj.begin(); i != n->adj.end(); ++i){ // error: no viable overloaded '='

            cout << n->adj[*i].v->name <<"(" << n->adj[*i].v->distance << ")" << " ";

            if(!n->adj[*i].v->visited){
                n->adj[*i].v->visited = true;
                q.push(*i); //no matching member function for call to 'push'
            }
        }
    }
}

解决方法

您的第一个错误消息:

错误:没有可行的重载'='

这与以下内容有关:

vector<int>:: iterator i;
for(i = n->adj.begin(); i != n->adj.end(); ++i) {

请注意,n->adj.begin()的类型为vector<adjVertex>::iterator。但是,变量i的类型为vector<int>::iterator。编译器错误将比您显示的错误多得多。这本来可以很好地解释问题。

这应该纠正错误:

for(vector<adjVertex>::iterator i = n->adj.begin(); i != n->adj.end(); ++i) {

自从您询问auto以来,这也是可以接受的:

for(auto i = n->adj.begin(); i != n->adj.end(); ++i) {

在这种情况下,i的类型将为vector<adjVertex>::iterator

第二个错误与之相关:

没有匹配的成员函数可调用“ push”

为此:

q.push(*i);

在这里,q的类型为queue<vertex*>,而*i的类型为int。如果应用我的上述修复程序,则*i的类型将为adjVertex,这将产生相同的问题。因此,您需要:

q.push(i->v);

回到第一个错误,有一种更现代的迭代方法(自C ++ 11起),使用基于范围的循环 :

for (auto& elem : n->adj) {

上面,它将遍历您的adj向量,使您可以通过值为elem的值adjVertex&访问其元素。因此,您可以使用vertex*访问该元素中的elem.v

,

我对我的代码做了些微改动以解决它。我没有使用迭代器(for循环中的int变量很好),而且我不需要像这样取消引用

n->adj[*i].v->name

这才是最终成功的

void getConnectedComponents(string buildingName,vertex *& node){
    //pointer to sourceVertex
    vertex *vStart;
    vStart = node;

    queue<vertex*> q; 
    
    
    vStart->visited = true;
    q.push(vStart); 
    vertex *n; //pointer to elements in queue
    while(!q.empty()){
       
        n = q.front();
       
        q.pop();
        
        for(int i = 0; i  < n->adj.size(); i++){
               if(!n->adj[i].v->visited){
                 
                   //cout << n->adj[i].v->name <<"(" << n->adj[i].v->distance << ")" << " ";
               
                n->adj[i].v->visited = true;
                q.push(n->adj[i].v);
               }
        }
    }
    cout << endl;
}