'Creating undirected weighted graph from adjancency matrix from a csv
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.
Solution 1:[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
Solution 2:[2]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | alseether |
Solution 2 | Christian Sagala |