简体   繁体   中英

Add edge to a directed graph (Adjacency list) implemented using Linked List in C++

I have search but can't find a anything specific to my case.

I wanna implement a graph in c++ using linked list only. My structure is as below:


 class Vertex
 {     
     public:
     Vertex(std::string name = "none");
     private:
         std::string name;
         Edge *edges;
         Vertex *next;
         Runnable *runnables;
};

 class Edge
 {
     public:
          Edge();
     private:
         Vertex *connectsTo;
         Edge *next;
 };

 class TaskGraph{
      public:
           TaskGraph();

      private:
           Vertex *head;
 };

I have a method to add vertices to the graph void addVertex(TaskGraph* taskGraph, const std::string&);

This method works well as I can print out all the vertices in the graph. On the otherhand, to add directed edge, I did something like this:

 void MyGraph::addEdge(TaskGraph* taskGraph, const string& src, const string& dest){

      //get to the source vertex: this is ok
      //get to the destination vertex: this is also ok 


      //add edge : the problem is here // s is source vertex while d is destination vertex.
      Edge *e = new Edge;
      e->connectsTo = d;
      if(s->edges == 0){
           s->edges = e;
      }else{
           s->edges->next = e;
      }
 }

After adding say 5 edges , only two is actually added (ie the first and list edges, others are being replaced). I figure out it's because of this line: " s->edges->next = e; " but can't figure out how to implement it correctly. Please help!!!

Thanks

You are breaking your list. when you insert the edge. So you first case always works. you just add e are your edge.

The other case will add e as second edge but will loose all other edges previously added.

try this instead:

  //add edge : the problem is here
  Edge *e = new Edge;
  e->connectsTo = d;
  //If there is already a list node pointing to in s->edges...
  if(s->edges != 0){
      //Then apply the existing list to the back of the new node.
      // this add the exiting edges to the new one so you do not break the list.  
      e->next = s->edges;  
  }
  //Apply e as the head of the list (pointing to it via s->edges).
  s->edges = e;

This algorithm adds the new edge at the front of the list so they will appear in reverse order as the order you added them in.

To keep edges in the same order as they were inserted you can do as suggested below looping or adding a tail pointer for the last edge in the list..

The most important here is that you understand what you where doing wrong.

You started with

 S->edges->NULL

you added an edge E1 you you get

 S->edges->E1.next->NULL

Now you added the second edge E2 and:

 S->edges->E1.next->E2.next->NULL

So far so good. But when you add E3 this what what happened:

 S->edges->E1.next->E3.next->NULL        lost link to  E2.next->NULL

This is why you only had 2 edges in your list no matter how many edges you tried to add. It is also called a memory leak because you have lost all references to the E2 instance and you cannot clean up those objects.

Ok, that said this is and example implementation for what the others where talking about in the comments below about how to keep the list in the same order as the edges you added. So E1 is first E2 second, etc...:

class Vertex
{     
    public:
       Vertex(std::string name = "none");
    private:
       std::string name;
       Edge *edges;
       Edge *lastEdge;  // this will keep track of the last edge in the list. 
                        // with this pointer you avoid having to loop through all
                        // the edges every time to add to the end.
       Vertex *next;
       Runnable *runnables;
};

void MyGraph::addEdge(TaskGraph* taskGraph, const string& src, const string& dest)
{
   //get to the source vertex: this is ok
   //get to the destination vertex: this is also ok 


   //add edge : the problem is here // s is source vertex while d is destination vertex.
   Edge *e = new Edge;
   e->connectsTo = d;
   if(s->edges == 0)
   {
        s->edges = e;
        // set the last edge to point to the first item.
        s->lastEdge = e;
   }
   else
   {
       // In this case the logic is simple you already know that
       // the list is not empty and that lastEdge is pointing at the
       // last edge in the list so just make the current lastEdge
       // point to the new edge. This will grow your list with e at 
       // the end.
       // Then update lastEdge to point to the new edge you just added.
       // so that is it pointing to the end of the list again. 
       s->lastEdge->next = e;
       s->lastEdge = e;
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM