0

I am implementing BFS algorithm. I wrote this code in my IDE.
SYSTEM:
Windows 10
Dev c++

May be error in bfs() function.I posted my all code just because of reference.
My C++ code :


#include<bits/stdc++.h>
using namespace std;

class Graph{
    int v; // number of vertices
    vector<int>*adj;
    public:
        /**
         * Constructor to initialize the graph.
         * @param v an integer: number of nodes in the graph
         */
        Graph(int V){
            this->v=V;
            this->adj=new vector<int>[V];
        }

        /**
         * This function add a new edge to the graph.
         * @param u an integer: representing a node in the graph.
         * @param v an integer: representing a node in the graph.
         * @param biDir a bool: true denotes bidirectional edge, unidirectional otherwise.
         */
        void addEdge(int u,int v,bool biDir=false){
            adj[u].push_back(v);
            if(biDir)
                adj[v].push_back(u);
        }
        /**
         * This function traverse the given graph using BFS traversal technique.
         * @param src a node: function starts traversing from this node.
         */
        void bfs(int src){
            // create a array of boolean to keep track of visited nodes.
            vector<bool>visited(this->v,false);
           // visited[0]=true;
            // make a queue and insert src into it
            queue<int>q;
            q.push(src); // insert src into queue
            // mark first node as visited
            visited[src]=true;
            while(!q.empty()){
                int node=q.front();
                // visit
                cout<<node<<" ";
                // remove this node from queue
                q.pop(); 
                // visit every node adjacent to node 'node' 
                // if that node not visited then visit and enque it.
                for(int adjNode:adj[node]){
                    if(!visited[adjNode]){
                        visited[adjNode]=true;
                        q.push(adjNode);
                    }
                }
            }

        }
         void print(){
            // for every vertex
            for(int i=1;i<this->v;i++){
                // every connected edge from vertex
                cout<<i<<"-> ";
                for(int node:adj[i]){
                    cout<<node<<" ";
                }
                cout<<endl;
            }
        }
};
int main(){
    Graph g(5+1);
    g.addEdge(1,2);
    g.addEdge(1,4);
    g.addEdge(4,6);
    g.addEdge(3,6);
    g.addEdge(2,5);
    g.addEdge(5,2);
    g.addEdge(6,3);
    g.addEdge(6,4);
    g.print();
    cout<<endl;cout<<endl;cout<<endl;cout<<endl;
    g.bfs(1);
    return 0;
}

Although this program is compiling fine. But while running, only print() function executes. Function bfs() does not executes.
It produces the following OUTPUT: generated by print() function.

1-> 2 4
2-> 5
3-> 6
4-> 6
5-> 2

When i changed this code in bfs()

vector<bool>visited(this->v,false);

TO this

 bool visited[this->v];
            for(int i=0;i<this->v;i++)
                visited[i]=false;

this code also does not executes bfs().

  • i don't know this can solve your problem or not. In my case when i reinstall compiler, then it works for me. – Rahul Apr 18 '20 at 13:37
  • 4
    *In my case when i reinstall compiler, then it works for me.* -- What?? I wish downvoting comments were available. More than likely, your program had undefined behavior, possibly due to uninitialized variables or out-of-bounds access. @OP -- Please do not reinstall your compiler. – PaulMcKenzie Apr 18 '20 at 13:37
  • I don't know. I am not a developer, just a student. So, when this happens for the first time with me, i simply reinstall dev c++.If you could solve this, then it will also helpful for me. – Rahul Apr 18 '20 at 13:40
  • First, why is your vector a pointer? You could have simply done `std::vector adj;` There is no need to introduce dynamically allocated memory. – PaulMcKenzie Apr 18 '20 at 13:40
  • I am dynamically creating vector. If there is any error, then it should produace any compilation error. –  Apr 18 '20 at 13:42
  • 2
    @rahulkumar -- You are mistaken. Just because a program compiles ok, does *not* mean it is logically correct or doesn't have bugs. All that compiling ok means is that the program has no syntax errors. Also, that `bits` header is not standard -- you should include the proper C++ headers. – PaulMcKenzie Apr 18 '20 at 13:43
  • @PaulMcKenzie -- You are right. But, i am not able to find bug that why my program simply terminates (crash)? –  Apr 18 '20 at 13:46
  • 1
    ***i am not able to find bug that why my program simply terminates (crash)?*** You need to get access to a debugger. Use that to track down where the crash occurs. – drescherjm Apr 18 '20 at 13:47
  • 1
    Second the debugger suggestion. If you don't know how to use a debugger, learn how. Not using a debugger is like driving without mirrors on your car. One specific problem I see is that you create a graph with 6 nodes (valid indices 0 -> 5), and then try to access the node with index 6. Not sure if that's your only problem but that's a big first one. The use of "5 + 1" when you create your graph is worrying. If you want 5 nodes, type 5. If you want 6 nodes, type 6. It makes me think you're trying to get clever with off-by-one display and introducing off-by-one errors. – JohnFilleau Apr 18 '20 at 13:50
  • 1
    Yes, one issue is that you are accessing the vector out-of-bounds. – PaulMcKenzie Apr 18 '20 at 13:53
  • 1
    @PaulMcKenzie -- `Also, that bits header is not standard ` `bits` header just includes the standard headers of `C++`. [link](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/precompiled/stdc%2B%2B.h) this is a link for source code of `bits/stdc++.h`. If any header had not included and when i use any function or `bla, bla...` out of that header. Then compiler will produce `it is not defined`. So, here compilation error should be presented. – Rahul Apr 18 '20 at 13:54
  • 1
    @Rahul -- Don't use that header. [Please read this](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h/31816096). I wish that g++ would remove that silly header, or prepare to get it deprecated and then removed from a future version. Also, if someone were to help by compiling your code, and that someone used Visual Studio, they have to take that silly header, remove it, and add in the proper headers, since there is no such header in Visual Studio (and probably other compilers). – PaulMcKenzie Apr 18 '20 at 13:55
  • All of your indexing into your array (and each vector in the array) should go from `i = 0` to `i < v` (or `i < .size()`). If you want your **interface** to be 1-indexed, THAT'S FINE, but you need to immediately convert any such 1-index to a 0-index when you enter the function (such as addEdge) or you need to convert your 0-index to a 1-index when you print. Don't use 1-indexes in the guts of your class. Translation should occur at the class interface - not within its guts. – JohnFilleau Apr 18 '20 at 13:55
  • @rahul there are many things that are perfectly legal to do in a language according to its syntax, but which should be avoided to increase the readability, maintainability, debugability, etc. of your program. Including `bits/stdc++.h` is up there with `using namespace std;` as a thing that is a worst-practice. – JohnFilleau Apr 18 '20 at 13:57
  • @PaulMcKenzie -- yeah! you are right. Rahul can you run this program after removing the header. Then tell us what's status. – Rahul Apr 18 '20 at 13:59
  • @Rahul replacing `` with `` and `` isn't going to solve this problem they're having. It will make the program better and improve their coding style, but won't fix the off-by-one indexing. – JohnFilleau Apr 18 '20 at 14:02

2 Answers2

1

You can just set the size to 7 and it'll work. your problem is that you're resizing the graph to have 6 nodes, yet accessing the 7th node (node with number 6 is considered the 7th node since indices start from 0). But anyways that's not the best way to solve the problem. If you want the number 6 to be included, then let the size of the graph be V + 1. also I noticed that you're using a pointer to a vector in the graph. I think it would be better if you use a vector of vectors instead. Here is a code that does the same thing with the problems fixed.

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

class Graph
{
    std::vector<std::vector<int>> _graph;

public:

    Graph(int size)
    {
        // nodes within the range [0..size] are valid.
        _graph.resize(size + 1);
    }

    void addEdge(int from, int to, bool undirected = false)
    {
        _graph[from].push_back(to);

        if (undirected)
            _graph[to].push_back(from);
    }

    void bfs(int source)
    {
        std::vector<bool> visited(_graph.size(), false);

        std::queue<int> queue;

        queue.push(source); 

        int depth = 0;

        while (!queue.empty())
        {
            int size = queue.size();

            std::cout << "Depth Level " << depth << " (with " << size << " unvisited nodes): ";

            while (size--)
            {
                int current = queue.front(); 

                std::cout << current << ' ';

                visited[current] = true;
                queue.pop();

                for (int node : _graph[current])
                    if (!visited[node])
                        queue.push(node);
            }

            std::cout << std::endl;
            depth++;
        }
    }
};

int main() {

    Graph g(6);
    g.addEdge(1, 2);
    g.addEdge(1, 4);
    g.addEdge(4, 6);
    g.addEdge(3, 6);
    g.addEdge(2, 5);
    g.addEdge(5, 2);
    g.addEdge(6, 3);
    g.addEdge(6, 4);

    g.bfs(1);
}

Output:

Depth Level 0 (with 1 unvisited nodes): 1
Depth Level 1 (with 2 unvisited nodes): 2 4
Depth Level 2 (with 2 unvisited nodes): 5 6
Depth Level 3 (with 1 unvisited nodes): 3
StackExchange123
  • 1,871
  • 9
  • 24
  • For anyone coming to this in the future - this answer is a band-aid. It shouldn't be solved like this. The off-by-one errors in the guts of the class should be fixed. This fix just makes the interface confusing. – JohnFilleau Apr 18 '20 at 14:27
  • @JohnFilleau you're right. I'm updating the answer. Thanks. – StackExchange123 Apr 18 '20 at 15:04
0

As i can see, you are using 1 based indexing for node value. I mean you are not considering 0 as a node in your graph. Any node in your graph starts from 1. While initializing graph you can set the value of graph size equals to number of nodes + 1 .
I mean,

Graph(int V){
            this->v=V+1;
            this->adj=new vector<int>[V];
        }

This can solve your problem.

Rahul
  • 310
  • 2
  • 13