0

I have done a lot of research and it seems that all of the examples are using an adjacency list to store the graph, and that seems to change how to find cycles within the graph. I am storing a graph using an adjacency matrix. This is the code for my graph. The isCyclic functions are what I have found, but don't work with an adjacency matrix, they also don't print the cycles.

#pragma once
#include"edge1.h"
#include <string>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <vector>

using namespace std;

class Graph
{
public:
    Graph(string f);
    void display(); 
    void computeTour();
    bool isCyclic();
private:
    char getChar(int n) { return (n + 'A'); }
    int getInt(char c) { return (c - 'A'); }

    void markCycles();
    void createGraphFromFile(string file);
    void addEdge(char a, char b);
    bool isCyclicUtil(int v, bool* visited, int parent);
    int totalNodes;
    int totalEdges;
    int **adj;
    bool *visited;
    vector<Edge> edges;
};

Graph::Graph(string f)
{
    createGraphFromFile(f);
}

void Graph::createGraphFromFile(string file)
{
    fstream fin;
    fin.open(file);

    fin >> totalNodes >> totalEdges;
    visited = new bool[totalNodes];
    adj = new int*[totalNodes];
    for (int i = 0; i < totalNodes; i++)
    {
        adj[i] = new int[totalNodes];
        for (int j = 0; j < totalNodes; j++)
        {
            adj[i][j] = 0;
        }
    }
    char a, b;
    while (fin >> a >> b)
    {
        addEdge(a,b);
    }
    fin.close();
}

void Graph::addEdge(char a, char b)
{
    Edge e;
    e.set(a, b);
    edges.push_back(e);
    int x = getInt(a);
    int y = getInt(b);
    if (x > totalNodes || y > totalNodes || x < 0 || y < 0)
    {
        cout << "Invalid edge!\n";
    }
    adj[x][y] = 1;
    adj[y][x] = 1;
}

bool Graph::isCyclicUtil(int v, bool* visited, int parent)
{
    visited[v] = true;

    for (int i = 0; i < totalNodes; i++)
    {
        if (!visited[i])
        {
            if (isCyclicUtil(i, visited, v))
                return true;
        }
        else if (i != parent)
            return true;
    }
    return false;
}

bool Graph::isCyclic()
{
    for (int i = 0; i < totalEdges; i++)
        visited[i] = false;
    for (int i = 0; i < totalEdges; i++)
    {
        if (!visited[i])
            if (isCyclicUtil(i, visited, -1))
                return true;
    }
    return false;
}

There is also an edge class that holds info about the edges:

#include <sstream>
#include <assert.h>
using namespace std;

class Edge
{  public:
     int toNode;  // Subscript of one endpoint in node array.  Nodes are stored as numbers, but printed as characters.
     int fromNode; // Subscript of other endpoint in node array
     int cycleID;  // Cycle which the edge is a member of, -1 if it is included in no cycle
     bool used;    // true if edge is used in final tour

   // Create a string version of Edge
   // Edge endpoints are stored as numbers, but printed as characters.
   string toString()
   { ostringstream os;  // allows string to act like stream to use stream operations
     char t = toNode + 'A';
     char f = fromNode + 'A';
       os << "   "<<f << "-"<<t  << "(" << cycleID << ")" ;
       return os.str();
   }  

   // if oneNode is an endpoint, return other endpoint
   int getOtherEndpoint(int oneNode)
   { if (fromNode==oneNode) return toNode;
     assert(toNode==oneNode);
     return fromNode;
   }

   // Set initial values of an edge from Node f to Node t
   void set(char f, char t)
   {  fromNode = f -'A';
      toNode = t-'A';
      cycleID = -1;
      used = false;
      cout << "creating Edge " << toString()<<endl;
   }
};

The graph I am working with has 7 nodes and 9 edges. Here is the output when creating the graph, just for reference. The (-1) is just the cycle ID for each edge, as they are all just being created, they don't belong to a cycle yet. That is where I need help.

creating Edge    A-B(-1)
creating Edge    B-C(-1)
creating Edge    C-A(-1)
creating Edge    A-E(-1)
creating Edge    E-D(-1)
creating Edge    D-A(-1)
   A B C D E
A  0 1 1 1 1
B  1 0 1 0 0
C  1 1 0 0 0
D  1 0 0 0 1
E  1 0 0 1 0

I can't figure out how to traverse the graph and find and print all of the cycles.

Hanna369
  • 61
  • 5
  • Your `isCyclic` function doesn't ever look at `adj` or `edges`. How could it ever work without looking at the state of the graph? – 0x5453 Apr 24 '18 at 19:00
  • 1
    Also, conceptually, whether you represent your graph as an adjacency matrix or an adjacency list is just an implementation detail. You should be able to detect cycles from outside the class without knowing how the graph is implemented. It may help to change your `Graph` interface to add functions allowing you to traverse the graph, which would in turn enable you to write your `isCyclic` function in a more generic way. – 0x5453 Apr 24 '18 at 19:05
  • yes, as i said, the isCyclic function is for adjacency list, it is just what I have found through research. I probably shouldn't have even added it when asking the question, it is just confusing me more. – Hanna369 Apr 24 '18 at 19:05
  • `isCyclic` doesn't look at a list either. As far as I can see by just looking at it, it will set `visited[0] = true` and then return true, that's all. – Arndt Jonasson Apr 24 '18 at 19:14
  • @Hanna369 In that case I would probably focus on figuring out the algorithm first. If it helps, draw some graphs on paper and figure out what steps you can take to find cycles. What you have now is pretty close; It makes sense to use a recursive algorithm, checking each node along the way to determine whether or not it has already been visited (if it has, you found a cycle and can return `true` immediately). Once you have a good grasp of the algorithm, then it should be fairly easy to apply it to your implementation. – 0x5453 Apr 24 '18 at 19:16

0 Answers0