creating undirected weighted graph from adjancency matrix from a csv

谁说我不能喝 提交于 2019-12-20 07:50:04

问题


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. can anyone help? 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. Help will be highly appreciated.


回答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



来源:https://stackoverflow.com/questions/47569823/creating-undirected-weighted-graph-from-adjancency-matrix-from-a-csv

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!