C++ 为什么在最坏的情况下无序集的再散列复杂性可能是O(n^2)?

C++ 为什么在最坏的情况下无序集的再散列复杂性可能是O(n^2)?,c++,stl,C++,Stl,我不明白为什么它不是线性的 对于有关multiset的类似问题,有一个很好的答案: 但是布景呢?每个键只能有一个元素 更新: 一个桶里有很多钥匙也不是问题。我们可以在一个线性时间内通过它们 我认为下面提到的正确答案是,标准中包含的O(n^2)重设复杂性允许开放寻址(可能是其他)实现。基本上,可以构建一个具有O(n)最坏情况重设时间的哈希集。甚至可以使用此属性构建一个多集,该属性仍然提供相同的保证,即具有相同键的元素在存储桶中彼此后面,因此您声明的链接是错误的。(好吧,并非完全错误,它承认可能存

我不明白为什么它不是线性的

对于有关multiset的类似问题,有一个很好的答案:

但是布景呢?每个键只能有一个元素

更新:

一个桶里有很多钥匙也不是问题。我们可以在一个线性时间内通过它们


我认为下面提到的正确答案是,标准中包含的O(n^2)重设复杂性允许开放寻址(可能是其他)实现。

基本上,可以构建一个具有
O(n)
最坏情况重设时间的哈希集。甚至可以使用此属性构建一个多集,该属性仍然提供相同的保证,即具有相同键的元素在存储桶中彼此后面,因此您声明的链接是错误的。(好吧,并非完全错误,它承认可能存在
O(n)
实现)

它的工作原理如下:

for each bucket b of old table
    for each element e in bucket b
        b' = new bucket of e
        prepend e before the first entry in b' // <---- this is the key optimization
对于旧表的每个桶b
对于铲斗b中的每个元件e
b'=新的e桶

在b'//重复线性加法-1+2+。。。n=n(n+1)/2即使每个键只有一个元素,也可能有多个具有相同哈希值的键,因此答案是相同的。@Mankarse:你错了,请看我的答案。好吧,您是对的,有多个键具有相同的散列值。然而,这并不意味着
O(n²)
rehashing行为。链接的问题有一个很好的答案。哪一部分让你困惑?哪一部分不清楚?请为您的问题添加更多详细信息。@gexicide:当然可以编写这样的容器,但标准不要求实现这样做。最坏情况下的再灰化性能是
O(n²)
(参见
[unord.req]/10
表103)。我删除了我的答案,因为它仍然没有显示需要二次型。关键是,密钥不需要是可排序的,但似乎该算法甚至不需要排序。我想最坏的情况是允许以最小的内存开销实现。@user2079303:是的,我现在也意识到了这一点。有了这个,我们甚至可以在不需要任何额外空间的情况下获得
O(n)
。请参阅我编辑的答案的最后一部分。@gexicide好的。但它只适用于链接;它不适用于开放寻址。但我求你了:我们为什么要防范一个根本不应该发生的角落案件呢?@Ali:对,公开演讲是行不通的。同样正确,对于
集合
来说,它是一个角盒。但对于
multiset
,这并不是一个特例。好的,OP询问了set,但他引用了一个多集合的链接,这个数据结构甚至是可能的。但您可能是对的,规范希望确保可能的实现也可以使用开放寻址。我将在我的答案中添加开放寻址的内容。考虑到bucket接口和insert对稳定引用的要求,我怀疑规范是否允许开放寻址。