【问题标题】:Graphs using Adjacency List in c++在 C++ 中使用邻接表的图
【发布时间】:2013-07-29 14:01:04
【问题描述】:

我正在尝试用 C++ 实现一个图形。我使用包含两个变量的结构来表示图中的节点 -
a) 一个包含有关节点的一些信息的整数。
b) 一个列表,其中包含与其相连的其他顶点的索引。
以下是代码。

// Graphs using adjacency list

#include <iostream>
#include <list>
#include <cstdlib>
using namespace std;

// structure to represent a vertex(node) in a graph
typedef struct vertex{
    int info;
    list<int> adj;   // adjacency list of edges contains the indexes to vertex
} *vPtr;             

int main(){
    vPtr node = (vPtr)malloc(sizeof(struct vertex));
    node->info = 34;            // some arbitrary value
    (node->adj).push_back(2);   // trying to insert a value in the list
    return 0;
}

代码编译正常,但在我推回列表中的一个元素时出现运行时错误。我的结构有什么问题吗?
我正在使用代码块和 GNU GCC、C++ 98 编译器来编译我的代码。

【问题讨论】:

  • vPtr 声明有些可疑。
  • @Jim :我不这么认为,因为代码只有在我推回列表时才会出现问题。如果我删除该行,那么代码就可以正常工作。

标签: c++ list graph structure adjacency-list


【解决方案1】:

malloc 是一个 C 函数 - 它不应该与 C++ 对象一起使用,which is very well explained here (简短回答:在 C++ 中,当你不处理 POD 类型时,std::list 在你的在这种情况下,您必须调用对象的构造函数才能使实际对象准备好使用,而malloc() 不会这样做。

You should used new instead。虽然malloc 只分配一块大小为vertex 的内存块,但new 这样做并且还通过调用它的构造函数来初始化std::list(有趣的是,当你调用delete() 时,你正在调用你的对象的析构函数)。

这里有一段代码适用于您的情况,但我建议您开始在 C++ 项目中使用更多 C++ 功能:

#include <iostream>
#include <list>
#include <cstdlib>
#include <new>

using namespace std;

// structure to represent a vertex(node) in a graph
typedef struct vertex{
    int info;
    list<int> adj;   // adjacency list of edges contains the indexes to vertex
} *vPtr;             

int main(){
    cout << "allocating memory for our vertex struct... \n";
    vPtr node = new vertex();
    node->info = 34;            // some arbitrary value
    (node->adj).push_back(2);   // trying to insert a value in the list
    cout << "cleaning allocated memory... \n";
    delete(node);

    return 0;
}

【讨论】:

  • 嗯,确实它强烈地改变了代码。但我认为这是必要的,因为问题的性质是使用了错误的工具来完成这项工作。
  • 我完全同意。但这是一个有趣的学术练习,可以了解 malloc 和 STL 如何交互(或不交互)。关于 malloc 不运行构造的见解很有趣。
  • 是的,我认为你有更好的答案,因为它解决了这个问题。 Streppel绕过了它,这可能是正确的做法,但没有解释事情。我会 +1 你的答案,至少我能做到....
  • @Jim,是不是 malloc 不做 stl 对象所需的东西?
  • 我认为 STL 可以做任何事情,但是一些熟悉不同方法的人有时想混合使用它们。一般来说,这可能不是最好的做法,但它确实发生了。
【解决方案2】:

几件事。

  1. 因为您使用的是malloc,所以从未调用过constructor,并且作为 这样的非原始成员 adj 永远不会被构造并且是 空。
  2. 您正在泄漏内存,因为您从未释放/删除任何动态分配的内存。

  3. 如果您使用 C++,为什么要使用 malloc 而不是 newdelete

  4. 对于 C++,您不必在 sizeof 中说 struct vertex。

要修复它,你可以这样做:

vPtr node = new struct vertex(); // also change to delete instead of free

// use current malloc line, change adj to be a pointer to a list and new it
// but this will cause additional problems for you since you really need to use a constructor for STL::list
node->adj = new list<int>;

你真的不应该在这里使用malloc

【讨论】:

  • 也许他不应该,但很高兴知道(无论如何)这些是如何相互作用的。
  • 我不认为 node->adj = new list;编译。
  • 糟糕,确实如此,当您将 adj 设为 ptr 时。
  • 是的,这正是我在评论中所说的你必须做的:-)
  • @Jim 别担心,伙计!干杯并感谢您的投票!这很适合我的第一个帖子答案是正确的永远不会得到爱:-p 找到了一些你的好帖子,我也艰难地通过了。这很有趣,但您偶尔会遇到必须将两者混合在一起的情况,特别是如果您还不能使用placement-new并且出于其他性能原因必须将它们混合在一起(调用new和malloc对延迟不利) .. 是的,我意识到 STL 也是如此..
【解决方案3】:

这是 UpAndAdam 的回答,写得很完整。

// Graphs using adjacency list
//
#include <iostream>
#include <list>
#include <cstdlib>
using namespace std;

// structure to represent a vertex(node) in a graph
typedef struct vertex{
    int info;
    list<int> *adj;   // adjacency list of edges contains the indexes to vertex
} *vPtr;             

int main(){
    vPtr node = (vPtr)malloc(sizeof(struct vertex));
    node->adj = new list<int>;
    node->info = 34;            // some arbitrary value
    (node->adj)->push_back(2);  // trying to insert a value in the list
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-07
    • 2015-06-16
    • 1970-01-01
    相关资源
    最近更新 更多