-1

I want to create undirected weighted graph of a given adjacency matrix by reading it from a csv. I can read it from a csv but I don't know how to draw its in graph. This is code for reading file.

int main(){

    ifstream ip("map.csv");

    if(!ip.is_open()) std::cout << "ERROR: File Open" << '\n';

    string first;
    string weight;

    while(ip.good()){
        getline(ip,first);
    
        getline(ip,weight);
    
        std::cout << "First: "<<first <<'\n';
    
        std::cout << "Weight: "<<weight<< '\n';
        std::cout << "-------------------" << '\n';
     }

    ip.close();
}

This is code for implementing it in graph.

class Graph {

     private:

      bool** adjacencyMatrix;

      int vertexCount;

      public:

      Graph(int vertexCount) {

            ip->vertexCount = vertexCount;

            adjacencyMatrix = new bool*[vertexCount];

            for (int i = 0; i < vertexCount; i++) {

                  adjacencyMatrix[i] = new bool[vertexCount];

                  for (int j = 0; j < vertexCount; j++)

                        adjacencyMatrix[i][j] = false;

            }

      }

 

      void addEdge(int i, int j) {

            if (i >= 0 && i < vertexCount && j > 0 && j < vertexCount) {

                  adjacencyMatrix[i][j] = true;

                  adjacencyMatrix[j][i] = true;

            }

      }

 

      void removeEdge(int i, int j) {

            if (i >= 0 && i < vertexCount && j > 0 && j < vertexCount) {

                  adjacencyMatrix[i][j] = false;

                  adjacencyMatrix[j][i] = false;

            }

      }

 

      bool isEdge(int i, int j) {

            if (i >= 0 && i < vertexCount && j > 0 && j < vertexCount)

                  return adjacencyMatrix[i][j];

            else

                  return false;

      }

 

      ~Graph() {

            for (int i = 0; i < vertexCount; i++)

                  delete[] adjacencyMatrix[i];

            delete[] adjacencyMatrix;

      }

};

This is how my file looks like.

C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11
C1,-1,20,-1,40,-1,-1,-1,-1,-1,-1,-1
C2,20,-1,-1,-1,80,-1,-1,-1,-1,-1,-1
C3,-1,-1,-1,-1,60,-1,-1,-1,-1,-1,-1
C4,40,-1,-1,-1,-1,200,-1,-1,-1,-1,-1
C5,-1,80,60,-1,-1,-1,100,-1,43,-1,-1
C6,-1,-1,-1,200,-1,-1,33,-1,-1,-1,-1
C7,-1,-1,-1,-1,100,33,-1,-1,-1,-1,-1
C8,-1,-1,-1,-1,-1,-1,-1,-1,4,-1,55
C9,-1,-1,-1,-1,43,-1,-1,4,-1,-1,-1
C10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,32
C11,-1,-1,-1,-1,-1,-1,-1,55,-1,32,-1

I don't know how to use my output from reading file into implementing the graph.

halfer
  • 19,824
  • 17
  • 99
  • 186
shahid hamdam
  • 751
  • 1
  • 10
  • 24
  • 1
    The `bool **adjacencyMatrix;` makes me afraid. I would use a `std::vector` (single dimension) instead and using access like `row * vertexCount + column`. So, you wouldn't have to struggle with all these `new`s and `delete`s. Btw. is there any reason why you don't store the weights in the adjacency matrix? (in this case, `std::vector` or `std::vector`) And, if you don't need weight `0` you could use `0` as indicator for "non-adjacence". (Remember, every `int` value represents a boolean also in C and C++ where 0 is false and anything else is true.) – Scheff's Cat Nov 30 '17 at 09:29
  • Once, we developed a special class to store and manage only the lower left triangle of a matrix (with or without main-diagnoale) to represent symmetric adjacencies without redundance. This, of course, saves memory, and you cannot get inconsistent asymmetrical entries but access is less performant as the computation of cell out of row and column is not quite as simple as described in my previous comment. – Scheff's Cat Nov 30 '17 at 09:33
  • Reading your question again I feel like your actual question is about reading the CSV file. In this case, please, try google "stackoverflow c++ read csv". This has already been asked many times. There must be something appropriate which might help you. – Scheff's Cat Nov 30 '17 at 09:40
  • `I don't know how to draw its in graph` what ?? – UmNyobe Nov 30 '17 at 09:41
  • Scheff I can read file but after reading I have to draw its undirected graph. How can I do that? Value I read from file are line by line. UmNyobe this also answer your question – shahid hamdam Nov 30 '17 at 17:48

2 Answers2

1

Here is my proposal.

First, i've decide to apply @Scheff modification (more or less), with a vector of vector as adjacency matrix. I think makes code cleaner than use row * vertexCount + column type access.

Graph class

#include <unordered_map>
#include <vector>
#include <string>

class Graph {
private:
    typedef std::vector < std::vector<int> > tAdjacencyMatrix;
private:

    tAdjacencyMatrix adj;

    int vertexCount;

public:

    Graph(int vertexCount) {
        this->vertexCount = vertexCount;
        for (int i = 0; i < vertexCount; i++) {
            std::vector<int> v;
            for (int j = 0; j < vertexCount; j++)
                v.push_back(0);

            adj.push_back(v);
        }
    }   

    void addEdge(int i, int j, int value) {
        if (i >= 0 && i < vertexCount && j > 0 && j < vertexCount) {
            adj[i][j] = value;
            adj[j][i] = value;
        }
    }   

    void removeEdge(int i, int j) {
        if (i >= 0 && i < vertexCount && j > 0 && j < vertexCount) {
            adj[i][j] = 0;
            adj[j][i] = 0;
        }
    }   

    bool isEdge(int i, int j) const {
        if (i >= 0 && i < vertexCount && j > 0 && j < vertexCount)
            return adj[i][j];   // 0 interpreted as false
    }

    std::string toString() const{
        std::string ret = "";
        for (int i = 0; i < vertexCount; i++) {
            ret += "V1: ";
            for (int j = 0; j < vertexCount; j++){
                ret += std::to_string(adj[i][j]);
                if (j != vertexCount - 1) ret += ", ";
            }
            ret += "\n";
        }
        return ret;
    }
};

I added a toString method to probe that it works fine.

Note: you can use adj.size() instead of vertexCount.

With this, my main look like:

Main

int main(){

    ifstream ip("map.csv");

    if (!ip.is_open()) std::cout << "ERROR: File Open" << '\n';
    string line;
    getline(ip, line);
    vector<string> tokens = splitString(line, ',');
    int vertexCount = tokens.size();

    Graph g(vertexCount);
    int v = 1;
    while (ip.good()){
        getline(ip, line);
        tokens = splitString(line, ',');
        for (int i = 1; i < tokens.size(); ++i){    // Note that starts in 1, avoiding "Cx" first element
            if (tokens[i].compare("-1") != 0){
                g.addEdge(v, i, atoi(tokens[i].c_str()));
            }
        }
        ++v;
    }

    ip.close();

    cout << g.toString() << endl;
    return 0;
}

Split string function:

SplitString

std::vector<string> splitString(const string &s, char delimiter){
    istringstream iis(s);

    vector<string> tokens;
    string aux = "";
    char c;

    while (iis.good()){
        c = iis.get();
        if (c == delimiter){
            tokens.push_back(aux);
            aux.clear();
        }
        else{
            aux.insert(aux.end(), c);
        }
    }
    tokens.push_back(aux); // Insert the last one (it has no ',' at the end)

    return tokens;
}

Note2: splitting function can surely be better, but i think this one is easier to understand

alseether
  • 1,889
  • 2
  • 24
  • 39
0

Create an implementation of an undirected graph that has weights. Save file with name weighted_undirected_graph.c. Terms and values ​​to be left to you. Explain each line of code and display the result of the weight graph you worked with.