简体   繁体   English

将边添加到使用C ++中的链接列表实现的有向图(邻接列表)中

[英]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. 我只想使用链表在c ++中实现图形。 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&); 我有一种方法可以将顶点添加到图中的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). 加入说5个边后,只有两个实际上添加(即第一和列表的边缘,其他人都被替换)。 I figure out it's because of this line: " s->edges->next = e; " but can't figure out how to implement it correctly. 我发现这是因为以下这一行:“ s-> edges-> next = e; ”,但无法弄清楚如何正确实现它。 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. 您只需添加e就可以了。

The other case will add e as second edge but will loose all other edges previously added. 另一种情况是将e添加为第二条边,但会放宽先前添加的所有其他边。

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 您添加了一条边缘E1

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

Now you added the second edge E2 and: 现在,您添加了第二条边E2并:

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

So far so good. 到现在为止还挺好。 But when you add E3 this what what happened: 但是,当您添加E3时,会发生什么情况:

 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. 这就是为什么无论您尝试添加多少条边,列表中都只有2条边的原因。 It is also called a memory leak because you have lost all references to the E2 instance and you cannot clean up those objects. 这也称为内存泄漏,因为您丢失了对E2实例的所有引用,并且无法清理这些对象。

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...: 所以E1是第一个E2第二个,依此类推...

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;
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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