假设我们有一个双向边的图,没有权重。如何存储它以便我不会浪费大量内存,使其快速并且可以快速访问每个顶点的邻居?我的意思是,直到现在为止...... {(1,2)(1,5)(1,3)(2,4)(2,3)}
我一直在使用数组:array[1][2]=1
意味着1和2之间存在连接。这有两个问题:
a)由于图表是双向的,(1,2)
表示也存在(2,1)
。如果我想稍后轻松访问2个邻居,我必须每次迭代进行两次更改:array[1][2]=1
,array[2][1]=1
b)当我知道某些顶点(比如5)只剩下一个邻居时,我必须在每个可能的array[5][x]
c)对于一百万个顶点的图表,这个怪物变得太大而无法在任何比赛中使用
你能帮助我并指出我解决问题的方法吗?
答案 0 :(得分:3)
看起来你想要一套地图。
std::map< int, std::set< int > >
因此,对于int,您可以在集合中存储其所有邻居的集合。您将需要函数来操作此集合。
如果节点数是可数的,即它们的范围从0到N并包含所有这些数字,那么您可以使用std::vector< std::set<int> >
,这样做会更有效。如果您有20,000个节点,也可以使用std::vector< std::bitset<N> >
或std::vector< boost::dynamic_bitset > >
,因此可以提供20,000个2500字节的位集(加上一点开销),每个= 50MB内存(大约)。
这是一个稍微紧凑的模型,你可以拥有但不是很多。如果你有一百万个顶点它将大约125GB,所以显然你不能使用这个模型,但应该使用该集。此外,迭代顶点以查看其邻居是一个比setset更快的操作。
除非有许多顶点完全没有邻居,并且它们是按顺序编号的,否则没有地图优于矢量的优势。
不确定你称之为“吨”的内存量。我刚刚放弃的模型使用常量内存,而集合映射使用的内存与您拥有的邻域关系数量成比例,但是当它变满时,它将比位集向量小得多,因此会消耗更多。
答案 1 :(得分:0)
您可以使用三角矩阵。这意味着,例如,如果x < y,则(x,y)将存在,但(y,x)将不存在 - 并且您将在(x,y)找到相应的值。
有关示例,请参阅http://www.codeguru.com/cpp/cpp/algorithms/general/article.php/c11211和https://stackoverflow.com/questions/8305186/isolating-triangle-array-items-and-evaluating-them-for-equality-then-outputting。