【问题标题】:c++ map implementation with good performancec++ map实现,性能好
【发布时间】:2014-02-26 17:20:27
【问题描述】:

我想将一些键映射到其他数据结构,其中键列表是从互联网接收的。

std::unordered_map 是 O(1),但最坏的情况是 O(N)
std::map 总是 O(log N)

是否有另一个地图实现具有 O(1) 最佳情况和 O(log N) 最坏情况性能?

【问题讨论】:

  • 您还可以使用键值对的排序向量向量来实现映射。这里插入是 O(N),搜索是 O(log N),但是缓存更好,因为键中没有使用指针。

标签: c++ data-structures


【解决方案1】:

正如您所指出的,std::unordered_map 的最坏情况是线性的,因此与其要求更好的最坏情况(不存在这样的容器 - 如果确实存在,则标准不会使用它,或者至少提供这样的变化?) 让我们考虑是什么导致最坏的情况,看看我们是否可以防止它。

在这种情况下,std::unordered_map (几乎可以肯定)是一个哈希图,所以最坏的情况发生在 当您插入的每个项目哈希到 sme 值并且它们全部链接到单个存储桶中(有效地使哈希图成为链表)。

所以只要你有一个合理的哈希函数,最坏的情况就不会发生,你最终会得到一个恒定时间的操作。

【讨论】:

【解决方案2】:

std::unordered_map 的最佳和最差性能在很大程度上取决于哈希函数的质量。最差的 O(N) 性能是当所有键映射到相同的哈希值时(即 100% 的冲突率)。所以,除非你有一个极其糟糕的散列函数,否则你不会真正得到那种最坏情况下的性能。

在确定哈希映射的性能时,它与数据的概率和统计数据密切相关。基本上,您拥有输入数据(键)的分布,然后将其映射到散列值的分布。如果您非常了解输入分布,则可以设计一个良好的散列函数,该函数将映射到散列值的均匀分布。如果您的哈希值分布非常均匀,那么发生冲突的可能性就很低,因此,您的存储桶(具有相同哈希值的值组)的大小平均会很小,这将导致非常良好的平均情况表现。你可以说平均情况下的性能是 O(B),其中 B 是桶的平均大小。你的哈希函数越好,碰撞概率越低,你的桶大小越小,你的平均性能就越好,这就是你应该追求的目标。

一般来说,你不能保证不会得到最差的性能 O(N),但你可以保证遇到这种糟糕情况的概率非常低。

也就是说,可能存在一种数据结构,它以一种可以加快查找速度的方式存储每个桶的元素,例如二叉树或排序数组。我不知道有任何特定的容器可以做到这一点,但它会将最坏的情况减少到大约 O(log(N)),但这也会是一个额外的负担(常数因素)。因此,归根结底,您必须对其进行测试才能确定。

【讨论】:

    【解决方案3】:

    这个怎么样,只是一个建议。

    Sudo code:
    
    my_hash = GenHash(key)
    
    std::unordered_map<my_hash, val, Hash = my_hash> map1   <---- Hash function of unordered_map should return its key. i.e. my_hash
    std::map<key, val> map2
    
    if my_hash is in map1
        map2[key] = val
    else
        val.k = key    <---- assumes key can be stored/found inside the value
        map1[my_hash] = val
    

    这样我们就可以停止在 unordered_map 中形成导致 O(N) 的链表。在最好的情况下,您只填写 map1。如果 sudo 代码不清楚,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-13
      • 1970-01-01
      • 1970-01-01
      • 2018-10-15
      • 1970-01-01
      • 2013-04-22
      相关资源
      最近更新 更多