0

while I understand the BFS conceptually I haven't grasped how to use an iterator and a queue to implement the BFS. I'd really appreciate it if somebody could give me some insight how to properly use the iterator in my code. Thank you.

I'm not even sure if an iterator is a good idea here, I tried to learn the auto type too but I'm not sure how to use that.

#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'
            }
        }
    }
}

Note: I solved my own question in the comments.

  • Sorry, just edited that out –  Nov 02 '20 at 02:42
  • 1
    This code needs less vertical whitespace. What is the actual problem with your code? Is there even a problem? It looks like you've implemented BFS with a queue here. The main issue I see is undefined behavior if `sourceVertex` is not found, which will likely result in a crash. – paddy Nov 02 '20 at 02:55
  • The compiler doesn't like my for loop. –  Nov 02 '20 at 03:00
  • Yes I see you edited this now to add actual error messages. That should have been much clearer in your question. This will be simple to answer. One moment. – paddy Nov 02 '20 at 03:00
  • Ok thanks I appreciate the help! –  Nov 02 '20 at 03:05
  • 1
    For future reference, when you write some code and you have compiler errors which you don't understand, please don't then post your program and say "I need to do -- help". Instead, you should post the actual error message and show the code it relates to. Make that the focus of your question. You could also try searching the internet for those kinds of errors, as you're definitely not the first person to run into difficulty with types in C++. – paddy Nov 02 '20 at 03:13
  • Also for future reference: see [mre]. For an error during compilation, it usually takes at most a dozen lines to reproduce the error; often half that. Keep the line triggering the error and just enough context to preserve the error message. – JaMiT Nov 02 '20 at 12:38

2 Answers2

0

Your first error message:

error: no viable overloaded '='

This is related to the following:

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

Note that the type of n->adj.begin() is vector<adjVertex>::iterator. However, the variable i is of type vector<int>::iterator. The compiler error would have had much more in it than what you showed. This would have explained the problem perfectly.

This should fix the error:

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

Since you asked about auto, that's also acceptable:

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

In this case, the type of i will be vector<adjVertex>::iterator.

The second error is related:

no matching member function for call to 'push'

That is for this:

q.push(*i);

Here, the type of q is queue<vertex*> and the type of *i is int. If you apply my above fix, then the type of *i will be adjVertex which is going to produce the same problem. So, you'd need:

q.push(i->v);

Going back to the first error, there's a more modern way to iterate (since C++11), using a range-based loop:

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

Above, this will iterate over your adj vector, giving you access to its elements via the value elem which will be of type adjVertex&. So you would be able to access the vertex* in that element with elem.v.

paddy
  • 60,864
  • 6
  • 61
  • 103
0

I made slight changes to my code to fix it. I didn't use the iterator (an int variable in the for loop was fine), and I didn't need to dereference like this

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

Here's what ended up working

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;
}