【问题标题】:Add edge to a directed graph (Adjacency list) implemented using Linked List in C++将边添加到使用 C++ 中的链表实现的有向图(邻接表)
【发布时间】:2014-12-17 15:57:38
【问题描述】:

我进行了搜索,但找不到特定于我的案例的任何内容。

我想在 C++ 中仅使用链表实现一个图形。我的结构如下:


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

我有一种方法可以向图中添加顶点 void addVertex(TaskGraph* taskGraph, const std::string&);

这种方法效果很好,因为我可以打印出图中的所有顶点。另一方面,为了添加有向边,我做了这样的事情:

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

添加 5 条边 后,实际上只添加了 两条(即第一条边和列表边,正在替换其他边)。我发现这是因为这条线:“s->edges->next = e;” 但无法弄清楚如何正确实现它。请帮忙!!!

谢谢

【问题讨论】:

  • 变量s是什么?
  • 看起来您正在使用Vertex 类的Edge* edges 成员作为指向单个Edge 对象的指针。如果您想支持一个顶点可以与多个其他顶点相邻的图形,这似乎不起作用。
  • s 是源顶点。 @rchang 我明白你的意思。我应该做些什么。谢谢
  • 你在做 s->edges->next = e;。但是如果s->edges->next的前一个值不为null(>列表中有2个元素)呢?

标签: c++ linked-list


【解决方案1】:

你打破了你的清单。当你插入边缘。所以你的第一个案例总是有效的。您只需添加 e 就是您的优势。

另一种情况将添加 e 作为第二条边,但会松开之前添加的所有其他边。

试试这个:

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

此算法将新边添加到列表的前面,因此它们会以与您添加它们的顺序相反的顺序出现。

要保持边缘与插入的顺序相同,您可以按照下面的建议进行循环或为列表中的最后一个边缘添加尾指针..

这里最重要的是你明白你做错了什么。

你从

开始
 S->edges->NULL

你添加了一条边 E1 你得到了

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

现在您添加了第二条边 E2 并且:

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

到目前为止一切顺利。但是当你添加 E3 时发生了什么:

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

这就是为什么无论您尝试添加多少条边,您的列表中都只有两条边。它也被称为内存泄漏,因为您丢失了对 E2 实例的所有引用,并且您无法清理这些对象。

好的,这就是其他人在下面的 cmets 中讨论的关于如何保持列表与您添加的边的顺序相同的示例实现。所以 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;
   }
}

【讨论】:

  • 嗨,它的工作。如何使边缘按照我添加它们的顺序出现(不反转)?这很关键!谢谢
  • 你需要做一个循环才能到达列表的末尾,然后在那里添加节点。
  • 或者做更多的记录保存并为您的列表保留头部和尾部参考,因此在末尾插入不需要完整的列表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-16
  • 2019-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多