我正在寻找一个关联集合,它支持在至少O(Log(N))时间内按键(删除不重要)检索和插入值,并且在代码方面具有非常低的内存开销大小和运行时内存消耗。
我这样做是为了用C编写的小型嵌入式应用程序,所以我试图最小化所需的代码量和消耗的内存量。
如果它不是用C ++编写的话Google sparse hash data structure是可能的,并且更简单。
我所知道的大多数哈希表实现都使用了相当多的额外空间,需要的空间至少是键值总数的两倍,否则每个条目需要额外的指针(例如桶链式哈希算法) 。在我的结构中,键值对只是两个指针。
目前我正在使用已排序的键/值对数组,但插入的是O(N)。我不禁想到必须有一种聪明的方法来改善插入的摊销运行时间,例如通过分组插入,但我没有取得任何成功。
我认为这在某些圈子里一定是一个比较着名的问题,所以为了使这不太主观,我想知道上述问题最常见的解决办法是什么?
[编辑:
可能相关的一些其他信息:
答案 0 :(得分:2)
查看binary search tree并克服最坏情况(搜索和插入都有O(n)复杂度)使用balanced tree。
答案 1 :(得分:1)
您可以使用不使用链接的哈希表,例如线性探测或布谷鸟哈希方案。支持实现只是一个数组,加载因子大约为0.5,开销不会太差,实现复杂性(至少对于线性或二次探测)并不算太多。
如果您想要一个良好的二进制搜索树实现,它具有出色的性能保证并且不易编码,请考虑查看splay树。它们保证分摊 O(lg n)查找,并且每个节点只需要两个指针。平衡步骤也比大多数平衡BST更容易。
答案 2 :(得分:1)
我可能会使用带有双重哈希的哈希表来解决冲突。一般的想法是哈希你的原始值,如果碰撞做了第二个哈希,给出一个步骤值,你将用于遍历数组来找到放置值的位置。这样可以很好地利用内存,因为它没有指针开销,并且在比线性探测更高的负载因子下保持合理的效率。
编辑:如果你想要改变现在正在做的事情,一种可能性是处理集群中的插入:保持一个排序的数组,以及一个单独的新插入集合。当新插入的集合变得太大时,将这些项合并到主集合中。
对于二级收藏,您有几个选择。您可以使用未排序的数组,并进行线性搜索 - 并且只是限制其大小,所以(比如)log(M),其中M是主数组的大小。在这种情况下,整体搜索仍为O(log N),不会产生任何内存开销,并且可以非常快速地保留大多数插入。当您将集合合并在一起时,您(通常)希望对辅助集合进行排序,然后与主集合合并。这使您可以在次要集合中的项目数上分摊线性合并。
或者,您可以将树用于辅助集合。这意味着新插入的项目会为指针使用额外的存储空间,但(再次)保持较小的大小会限制开销。