具有良好性能的c++映射实现
c++ map implementation with good performance
我想将一些键映射到其他数据结构,其中键列表是从互联网接收的。
std::unordered_map
是O(1),但最坏情况O(N)std::map
总是O(log N)
是否存在另一种具有O(1)最佳情况和O(log N)最差情况性能的映射实现?
正如您所指出的,std::unordered_map
的最坏情况是线性的,因此,与其要求更好的最坏的情况(不存在这样的容器-如果存在,标准不会使用它,或者至少提供这样的变体?),不如考虑导致最坏情况的原因,看看我们是否可以防止它。
在这种情况下,std::unordered_map
(几乎可以肯定)是一个哈希图,因此最坏的情况发生在,当您插入的每个项目都哈希到sme值,并且它们都链到一个桶中(有效地使哈希图成为链表)。
因此,只要你有一个非常合理的散列函数,最坏的情况就永远不会发生,你最终会得到一个恒定的时间运算。
std::unordered_map
的最佳和最差性能在很大程度上取决于哈希函数的质量。最差的O(N)性能是当所有密钥映射到相同的哈希值时(即,100%的碰撞率)。所以,除非你有一个非常糟糕的散列函数,否则你不会得到最坏的性能。
当涉及到确定哈希图的性能时,它在很大程度上与数据的概率和统计数据有关。基本上,您有一个输入数据(键)的分布,然后将其映射到哈希值的分布。如果你很了解你的输入分布,你可以设计一个好的哈希函数,它将映射到哈希值的均匀分布。如果哈希值的分布非常均匀,那么冲突的概率很低,因此,存储桶(具有相同哈希值的值组)的大小平均会很小,这将导致非常好的平均情况性能。您可以说,平均情况性能为O(B),其中B是存储桶的平均大小。哈希函数越好,碰撞概率越低,存储桶大小越低,平均性能就越好,这就是你应该追求的目标。
一般来说,你不能保证你不会得到最差的性能O(N),但你可以保证遇到这种坏情况的概率会很低。
也就是说,可以有一种数据结构来存储每个桶的元素,使其查找速度更快,例如二进制树或排序数组。我不知道有什么特定的容器可以做到这一点,但它会将最坏的情况减少到大约O(log(N)),但这也会是一个额外的负担(常数)。所以,在一天结束的时候,你必须测试它才能确定。
这个怎么样,只是一个建议。
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
通过这种方式,我们可以停止在导致O(N)的无序映射中形成链表。在最好的情况下,只填充贴图1。如果sudo代码不清楚,请告诉我。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 将函数类成员映射到类本身内部
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 使用std::函数映射对象方法
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- C++映射分割错误(核心转储)
- 内联映射初始化的动态atexit析构函数崩溃
- 使用"std::unordereded_map"映射到"std::list"对象
- 如何从多映射中删除特定的重复项
- 在未初始化映射的情况下,将值插入到映射的映射中
- QT通过C++添加映射QML项目
- 在c++中访问int到类对象的映射时出错
- 在C++中搜索嵌套多映射值
- 错误处理.将系统错误代码映射到泛型
- C++匿名结构作为std::映射值
- 如何从存储在std::映射中的std::集中删除元素
- 递归无序映射
- 正在VS调试器中监视映射条目