C++ 具有O(1)插入(摊销)和O(n)迭代的容器

C++ 具有O(1)插入(摊销)和O(n)迭代的容器,c++,algorithm,containers,C++,Algorithm,Containers,我正在寻找一个类似集合的容器类,它具有以下基本属性: 已摊销O(1)个插入时间,忽略重复插入 有O(n)个迭代时间(特别是O(容量)不可接受) 重复使用内存/仅在超过当前容量时分配 用例是我有一个更大的对象容器。在每个循环中,我将向这个新容器添加这些对象的子集。该子集可以是1-5个对象,也可以是整个集合的10%。然后我迭代这个新集合中的对象。对象的每个循环都将被清除,并重新开始处理 我最初的方法是在对象上使用一个入侵布尔值,指示它是否属于这个新集合。因此,插入是真正的恒定时间,并且不使用新内存。

我正在寻找一个类似集合的容器类,它具有以下基本属性:

  • 已摊销O(1)个插入时间,忽略重复插入
  • 有O(n)个迭代时间(特别是O(容量)不可接受)
  • 重复使用内存/仅在超过当前容量时分配
  • 用例是我有一个更大的对象容器。在每个循环中,我将向这个新容器添加这些对象的子集。该子集可以是1-5个对象,也可以是整个集合的10%。然后我迭代这个新集合中的对象。对象的每个循环都将被清除,并重新开始处理

    我最初的方法是在对象上使用一个入侵布尔值,指示它是否属于这个新集合。因此,插入是真正的恒定时间,并且不使用新内存。然而,迭代是次优的

    我尝试了一个
    boost::unordered_set
    ,但性能比我原来的方法差。大概是因为,作为散列映射,它无法满足第2点


    第#3点是相关的,因为我在一个延迟级别上编码,内存分配的成本非常大。因此,具有连续分配的容器不太可能运行良好。

    使用第一种方法来检测元素是否已经在集合中(哈希映射)。并将其放入列表中进行迭代。

    您可以使用链接哈希集。在java中。我不知道C++中是否存在一个实现它的库,但是这个想法很简单:有一个主菜,让主菜也形成一个.< /p>
    迭代在链表上,从哈希集进行插入。请注意,这种方法只允许在列表的背面插入列表。

    您可以通过添加链接列表来改进方法

    将有指向插入对象的指针(或任何合适的标识符)的链接列表。此外,将布尔变量保留在每个对象中,以了解它是否已插入列表。

    尝试。它可以满足您的目的:

  • 插入O(log(log(n))
  • 迭代O(log(log(n))
  • 记忆。。。好吧,请阅读提供的链接

  • 我认为O(1)插入和重复检测不可能同时进行。@aschepler,几乎所有哈希映射都可以实现这一点(至少摊销)。您可以使用通用哈希集,并对整个程序或特定哈希集使用专门的内存管理。这不是一件容易的事情,但是如果您的内存分配成本异常高,那么标准内存分配算法可能不合适?除非你使用的是某种疯狂的数据结构。@edA-qamort-ora-y:你在这些元素上有好的哈希函数吗?具体地说,我考虑使用OpenAddressing来实现哈希表,但为了满足插入
    O(1)
    的要求,您需要限制尝试查找插槽的次数。请注意,您还必须直接从集合中的每个元素连接到列表中的元素,以允许删除元素[如果需要]。@amit,奇怪的是,删除一个元素没有成本限制。通常只调用
    clear
    ,这当然应该是常数时间。@edA-qamort-ora-y:如果不需要删除,那么我认为这种方法应该可以。如果需要删除,应该在两个数据结构中的元素之间引用。@edA-qamort-ora-y:
    clear
    不是常数时间,它调用每个对象的析构函数!此外,使用
    列表
    ,您需要单独释放列表中的每个节点,即使使用
    deque
    ,您仍然会遇到这个问题(尽管没有那么多)。@MatthieuM.:这有关系吗?也许他已经建立了自己的mem manager,在那个里他可以在短时间内扔掉所有的记忆……是的,这是一种想法。谢谢,谢谢,我会再看的。它可能不起作用,因为与元素数(最多几百个)相比,我的键大小相对较大(64位)。实际上,不完全是这样,
    list
    是通用的,而链表精确地实现了一个。考虑到严格的内存限制(点3),链接列表似乎不合适,除非你认为容量总是严格地等于大小……我从你所说的话中一个字也听不懂。我不是说如果这是重点的话,就应该使用
    std::list
    。没有关系。。。