【发布时间】:2025-12-20 00:20:12
【问题描述】:
我不明白,为什么 erase 方法的 std::unordered_set 在最坏的情况下(其中 N 是元素数)复杂度为 O(N)?标准 (n4296) 说明所有三个版本的 erase 方法在最坏的情况下都具有 O(a.size()) 复杂性(a 是容器),并且仅使迭代器无效指向已擦除的元素,但不是所有的迭代器(即不会发生重新散列)。即使对于采用一个迭代器参数并且在平均情况下具有恒定复杂性的版本也是如此。我认为这是因为 erase 版本返回一个迭代器到下一个元素,这需要在擦除元素之后找到第一个非空桶,它给出了 O(a.bucket_count()) 复杂性,但不是 O(a.size())!。元素的数量与桶的数量不成正比。例如:
#include <iostream>
#include <unordered_set>
using namespace std;
int main()
{
std::unordered_set<int> aSet;
aSet.insert ({125, 126});
aSet.rehash (1000);
cout << aSet.size() << endl;
cout << aSet.bucket_count() << endl;
}
输出是
Size: 2
Bucket count: 1031
一个容器的大小只有2,bucket_count是1031。当erase方法被调用时,它会寻找下一个非空的bucket,这个bucket可以放在最后,即复杂度是O(a.bucket_count()),但不是 O(a.size())。标准给出 O(a.size()) 复杂度的原因是什么?
【问题讨论】:
-
认为现有的答案误解了这个问题。一个好的实现不必在每个桶中查找要擦除的元素,但最坏的情况除外,即所有桶都已满。因此,复杂度小于
O(a.bucket_count()),除非a.bucket_count()等于或大于a.size()。 -
O(bucket_count())部分不正确。见LWG 579。
标签: c++ c++11 stl containers unordered