我正在执行类似于 N 维卷积的操作,但会在我继续进行时组合彼此接近的值,以节省内存和时间。
- 我在数组中寻找一个键。
- 如果我找到密钥,我将添加到存储在该密钥中的值。
- 如果我没有找到密钥,我会找到下一个最高和下一个最低的密钥。
- 如果两个邻居中的较近者足够接近,那么我会使用该键值对进行累加。
- 否则我添加一个新的键值对。
关键是双。它总是积极的,永远不会是无限的。(我专门处理零。)我预计值的范围从几美分到高达 1000 亿。随着算法继续保持最大数组大小在 10,000 和 1,000,000 之间,舍入粗糙度将发生变化。(只有测试才能揭示速度、内存和准确性之间权衡的最佳点。)由于值的范围与数组大小的关系,直接寻址是不切实际的;我需要稀疏存储。
天真的方法是使用 List 并执行 BinarySearch 来查找键或插入点,然后从那里继续。这对于找到最近的键来说很快,可以按键顺序迭代,但是插入很糟糕。(我不需要执行删除!外循环中的每次迭代都会从头开始创建一个新列表。)
推荐什么数据结构?Wikipedia 提到了一些,例如 Trie、Judy 数组等。
(几年前我实现了一些类似 Trie 的东西,但那是在 java 中实现的,花了我一周的时间来实现,而且很棘手。我时间紧迫。)
更新:
SortedSet 的建议使我修改了我的要求。虽然找到下一个最低键和下一个最高键是我完成任务的方式,但 SortedSet.GetViewBetween 以不同的方式处理事情。因为我只是想看看是否有一个足够接近的值可以聚合,并且我有一定的舍入粒度 G,所以我可以使用
var possibilities = mySet.GetViewBetween(x - G, x + G)
如果该集合为空,我需要添加。如果不是,它可能是一个小集合,我会遍历它。
我需要进行性能测试,看看它是否足够快。但即使没有,具有相同合约的另一个集合也是 FindNextHighestKey 和 FindNextLowestKey 的可接受替代方案。
更新 2:
我决定使用普通字典,并使用自定义舍入函数将键强制放入存储桶中。按排序顺序迭代项目并不重要,通过使用这个舍入函数,我可以找到“足够接近”的值来聚合。我不会在迭代期间更改粒度;每次完成与新维度的卷积时,我都会对其进行调整。每次迭代我都会创建一个新数组来保存该遍的结果。