【问题标题】:Time complexity of unordered_set<int> find methodunordered_set<int> find 方法的时间复杂度
【发布时间】:2017-02-27 14:02:00
【问题描述】:

unordered_set&lt;int&gt;find方法的时间复杂度是多少?

还有可能改变散列函数吗?

【问题讨论】:

  • 从您问题中的链接中,您可以发现复杂性具有“恒定”的平均情况和“容器大小线性”的最坏情况。您究竟在寻找哪些其他信息信息?此外,您可以通过更改 unordered_setHash 模板参数或通过为您的类型专门设置 std::hash&lt;T&gt; 模板来更改哈希函数
  • 在@jogojapan 答案中查看here 中的哈希函数示例。

标签: c++11 stl time-complexity unordered-set


【解决方案1】:

unordered_set中find方法的时间复杂度是多少?

...它就在您链接的页面中:

复杂性

平均情况:常数。

最坏情况:容器大小呈线性关系。


还有可能改变散列函数吗?

是的。再次,看at the documentation

std::unordered_map 采用Hash 模板参数。这是一个自定义点,您可以在其中注入自己的哈希逻辑。自定义 Hash 必须满足 Hash 概念。

【讨论】:

  • 页面没有具体讲过INT类型。
  • @navidmahdian:这有什么关系?如果它没有专门讨论一个类型,则意味着它对所有类型都有效。
  • 这是真的,但我认为 int 类型可能总是在 O(1) 中找到一个元素,因为散列更容易
  • 搜索的复杂度与key的散列复杂度无关。虽然std::hash&lt;int&gt;{}( 2 ) 可能会返回整数本身,但容器仍然必须探测并与该整数键比较容器中包含的值。我不知道你期待什么样的魔法,但如果你有研究表明所有情况下的 O(1) (例如,密钥永远不会在存储中发生冲突),那么请分享它
【解决方案2】:

我猜你对默认的 max_load_factor 为 1 感到困惑。当你在 unordered_set 中插入一个 int x 时,它会进入存储桶 i(i=x%number of buckets)。因此,您可以想象,即使散列函数不会发生冲突,因为它会将每个 int 映射到自身,在某些情况下,mod 操作也会发生“冲突”。例如,如果按顺序插入 1、4 和 6,则 1 和 6 将在同一个存储桶中,查找函数将需要遍历存储桶才能找到它们。只有当负载因子达到最大负载因子时才增加存储桶的数量。负载因子是每个桶的元素数量的算术平均值。所以实际上每个桶中可以有多个元素,甚至可以在同一个桶中拥有相同的所有元素。在这种情况下,查找集合内的元素将需要在桶内进行传统的顺序搜索 (O(n))。这里有一个例子:

unordered_set<int> n;
n.insert(1);
n.insert(12);
n.insert(23);
n.insert(34);
n.insert(45);

在这种情况下,每个 int 都在存储桶 1 中,因此当您查找 56 (56%11 = 1) 时,您需要遍历整个存储桶(大小为 n,O(n))。加载因子为 0.4545(5 个元素 / 11 个存储桶),因此不添加存储桶。您可以减少 max_load_factor(某些语言使用 0.75 的负载因子),但这会增加重新哈希的次数,因为您需要更频繁地保留存储桶(保留过程是摊销常数,因为它使用相同的方法 std ::vector 使用,这就是为什么在示例中我们有 11 个桶)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-15
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多