在 C++ 中使用邻接表的图
Posted
技术标签:
【中文标题】在 C++ 中使用邻接表的图【英文标题】:Graphs using Adjacency List in 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 :我不这么认为,因为代码只有在我推回列表时才会出现问题。如果我删除该行,那么代码就可以正常工作。 【参考方案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】:几件事。
-
因为您使用的是
malloc
,所以从未调用过constructor
,并且作为
这样的非原始成员 adj
永远不会被构造并且是
空。
您正在泄漏内存,因为您从未释放/删除任何动态分配的内存。
如果您使用 C++,为什么要使用 malloc
而不是 new
和 delete
?
对于 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这是 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;
【讨论】:
以上是关于在 C++ 中使用邻接表的图的主要内容,如果未能解决你的问题,请参考以下文章
采用邻接表存储的图的深度优先遍历算法类似于二叉树的先序遍历,为啥是先序呢?