0

我有一张很大的桌子:

id1 id2 count
1   234   4
1    5    123
1   432   5
23  234   7

id1 和 id2 有许多不同的值。count 的数值有限(1-30000 或其他),我知道它们中的大多数等于 1。

当我将这张表存储在 .net 字典中时,它需要大约 10gb 的内存。我想找到内存高效的数据结构来存储这些数据。

完美的哈希可能是理想的解决方案,但问题是冲突。我可以获得表中不存在的 id 的值。也许 DAWG 可以提供帮助?或者是其他东西?


数据结构的主要目的是通过 id1 和 id2 进行计数。

4

2 回答 2

1

如果几乎所有的计数都是 1,那么您可以使用两个数据结构:一个包含所有计数为 1 的 id 对的 HashSet,以及一个用于计数大于 1 的 id 对的字典。这使得递增和检查计数有点慢,但它应该节省一些空间。(我不知道 .Net 数据结构在内部是如何布局的,所以我不敢猜测,但如果是 C++,我会说它会减少 25-30% 的空间消耗,具体取决于值“几乎所有”。)

如果这还不足以节省空间,这里是一些可能性的概述,尽管它可能需要大量工作才能获得不确定的收益:

一般来说,容器数据结构的成本由元素的数据大小加上一些每个元素的开销,再加上一些每个数据结构的开销组成。哈希表具有中等数量的每个元素开销(一个链接到桶中的下一个元素,加上分配/对齐开销);并且二叉树有很多每个元素的开销(两个或更多通常三个链接,加上分配/对齐开销)。从技术上讲,向量没有每个元素的开销,但它们通常被过度分配以减少插入时间,因此您应该将它们视为每个元素的开销为 50-100%。

一个后果是,如果您想出一种减少元素数量的方法,您通常可以节省空间。例如,您可以使用 id-pairs 的 HashSet,正如我上面建议的那样。但是,如果单个 id1 值比对少得多——即,如果 id 重复——那么您可以将其替换为将 id1 映射到 id2 向量的字典,这可能会减少开销。这样做有一个很大的缺点:它使查找和插入变得更加昂贵;此外,只有当哈希表每个元素的开销大于预期的向量过度分配开销时,它才会有所帮助。

于 2013-04-27T03:25:03.737 回答
0

你对 id1 和 id2 有一个相当小的上限吗?如果是这样,那么您可以将它们存储为一个数字;例如,如果两个数字的上限均为 255,则可以将它们存储为 id = id1 + id2 * 256; 如果需要,您可以提取 id1 = id % 256 和 id2 = id / 256 (使用整数除法)

现在每个 id 对都有一个索引,并且由于大多数计数为 1,因此您可以将其存储为稀疏数组(通常稀疏数组的“空”值是 0 或 null,在您的情况下它们是重新 1)

如果没有将两个 id 组合成一个索引的好方法,那么您可以将其存储为一个稀疏矩阵,其中 id1 作为 x 值,id2 作为 y 值(反之亦然)

于 2013-04-26T13:43:38.543 回答