【发布时间】:2013-04-10 11:52:09
【问题描述】:
所以我遇到了一个编程竞赛问题,涉及在不同的图表上运行大量 DFS。
起初我将我的图(邻接表表示)表示为一个集合向量:
vector< set<int> > graph;
每次我使用空集时,还要根据给定的节点数初始化一个图:
set<int> tmpSet;
我这样初始化它:
for(int j=0;j<N;j++)//N was the number of nodes needed for the graph
graph.push_back(tmpSet);
我用过
graph.clear();
每次清空图表。
为了之后插入边,我使用了 std::set 的插入功能。
//Insert directed edge from u to v
graph[u].insert(v);
graph[v].insert(u);
结果是程序消耗了太多内存,速度太慢而无法通过测试。使用 push_back 函数的 std::list 也发生了同样的事情,这是一个 constant 时间操作。然后,当我更改为 std::vector 时,内存消耗变得最小,我在 3 秒内通过了测试,而 std::set 和 std::list 甚至在 20 秒内都无法通过测试。
我的问题是它与释放内部集合和列表的空间有关,但是向量的行为如何不同?
所以我的问题是,是否有人可以解释为什么会发生这种情况,以便我可以更好地理解 stl 容器在诸如您在另一个容器中有一个容器的情况下的行为。
编辑:一些额外信息:节点数约为 N=3000,测试次数超过 1000。这意味着我必须创建 1000 多个图表,所有图表都保存在变量“图表”中。我也知道 set 在 O(lgn) 时间内插入,而 vector 和 list 在 O(1) 中,所以我理解为什么 set 只需要比向量长一点 。但是为什么 std::list 也失败了?另外让我提一下,set 和 list 使用 100Mb 的内存完成,而 vector 使用 3Mb 完成
好的,最终编辑,这是我的代码,用于准确显示我如何使用图表(列表版本)。程序中没有其他任何地方发生任何内存释放或更改图形数据。
vector< list<int> > graph;
list<int> tmpList;
int T; //num of test cases
int N; //num of nodes
int M; //num of edges
int main ()
{
int u,v;
scanf("%d",&T);//Read test cases
for(int i=0;i<T;i++){
scanf("%d %d",&N,&M);//Read number of nodes and number of edges
for(int j=0;j<N;j++)
graph.push_back(tmpList);
for(int j=0;j<M;j++){
scanf("%d %d",&u,&v);//Read edge from u to v
graph[u].push_back(v);
graph[v].push_back(u);
}
dfs();
graph.clear();
}
}
【问题讨论】:
-
当您删除测试逻辑完全并简单地加载您的容器,然后释放它们时,表现出的行为是什么?提供展示您观察到的行为的 SSCCE 的可能性很小吗?您是否考虑过“清除”的交换/清除成语?再说一次,在您的“测试”期间容器是如何访问/枚举的?如果您想要一个不是纯粹猜测/推测的具体答案,可能需要提供更多信息。