如果几乎所有的计数都是 1,那么您可以使用两个数据结构:一个包含所有计数为 1 的 id 对的 HashSet,以及一个用于计数大于 1 的 id 对的字典。这使得递增和检查计数有点慢,但它应该节省一些空间。(我不知道 .Net 数据结构在内部是如何布局的,所以我不敢猜测,但如果是 C++,我会说它会减少 25-30% 的空间消耗,具体取决于值“几乎所有”。)
如果这还不足以节省空间,这里是一些可能性的概述,尽管它可能需要大量工作才能获得不确定的收益:
一般来说,容器数据结构的成本由元素的数据大小加上一些每个元素的开销,再加上一些每个数据结构的开销组成。哈希表具有中等数量的每个元素开销(一个链接到桶中的下一个元素,加上分配/对齐开销);并且二叉树有很多每个元素的开销(两个或更多通常三个链接,加上分配/对齐开销)。从技术上讲,向量没有每个元素的开销,但它们通常被过度分配以减少插入时间,因此您应该将它们视为每个元素的开销为 50-100%。
一个后果是,如果您想出一种减少元素数量的方法,您通常可以节省空间。例如,您可以使用 id-pairs 的 HashSet,正如我上面建议的那样。但是,如果单个 id1 值比对少得多——即,如果 id 重复——那么您可以将其替换为将 id1 映射到 id2 向量的字典,这可能会减少开销。这样做有一个很大的缺点:它使查找和插入变得更加昂贵;此外,只有当哈希表每个元素的开销大于预期的向量过度分配开销时,它才会有所帮助。