我需要创建一个查找函数,其中(X,Y)对对应于特定的Z值。对此的一个主要要求是我需要尽可能接近O(1)复杂度。我的计划是使用unordered_map。
我通常不使用哈希表进行查找,因为查找时间对我来说从未如此重要。我是否认为只要我构建了没有冲突的unordered_map,我的查找时间就是O(1)?
我关心的是,如果无序地图中没有关键字,那么复杂性就会变得很复杂。例如,如果我使用unordered_map :: find():来确定我的哈希表中是否存在键,那么它将如何给我一个答案呢?它是否实际迭代了所有键?
我非常感谢帮助。
答案 0 :(得分:6)
标准或多或少要求使用铲斗进行碰撞 分辨率,这意味着实际的查找时间会 可能是相对于元素数量的线性 桶,无论元素是否存在。 有可能使它成为O(lg N),但通常不会这样做, 因为存储桶中的元素数量应小, 如果正确使用哈希表。
为了确保存储桶中的元素数量很少,您就可以了
必须确保散列函数有效。什么
有效的手段取决于被散列的类型和价值。
(MS实现使用FNV,这是最好的之一
通用哈希周围,但如果你有特殊的知识
您将看到的实际数据,您可能会做得更好。)
另一件可以帮助减少每个元素数量的事情
铲斗是为了强制更多的铲斗或使用更小的载荷系数。
对于第一个,您可以传递最小初始数
bucket作为构造函数的参数。如果你知道的话
您可以在地图中使用的元素总数
以这种方式控制负载系数。你也可以误认为最低限度
表格填写后,通过调用的桶数
rehash
。否则,有一个功能
您可以使用std::unordered_map<>::max_load_factor
。它
不保证做任何事情,但在任何合理的情况下
实施,它会。请注意,如果您已在已使用它
填写unordered_map
,您可能需要打电话
unordered_map<>::rehash
之后。
(关于标准,有几点我不明白
unordered_map:为什么加载因子是float
,而不是。{
double
;为什么不要求有效果;为什么呢
不会自动为您调用rehash
。)
答案 1 :(得分:3)
在散列数据结构中没有冲突是非常困难的(对于给定的散列函数和任何类型的数据,如果不是不可能的话)。它还需要一个完全等于键数的表大小。不,它不需要那么严格。只要哈希函数以相对统一的方式分配值,您将具有O(1)
查找复杂性。
哈希表通常只是带有链接列表的数组,它们处理冲突(这是链接方法 - 还有其他方法,但这可能是处理冲突最常用的方法)。因此,要查找某个值是否包含在存储桶中,它必须(可能)迭代该存储桶中的所有值。因此,如果散列函数为您提供统一分布,并且有N
个桶和总共M
个值,则每个桶应该(平均)M/N
个值。只要此值不太大,就可以O(1)
查找。
所以,作为对你的问题的一个冗长的回答,只要哈希函数是合理的,你将得到O(1)
查找,它必须迭代(平均){{1} }键给你一个“否定”的结果。
答案 2 :(得分:1)
与任何哈希表一样,最坏的情况总是线性复杂度(编辑:如果您构建的地图没有像您在原始帖子中所述的任何冲突,那么您将永远不会看到这种情况) :
http://www.cplusplus.com/reference/unordered_map/unordered_map/find/
<强>复杂性强> 平均情况:不变。 最坏情况:容器尺寸呈线性。
返回值 如果找到指定的键值,则为元素的迭代器;如果在容器中未找到指定的键,则为unordered_map :: end。
但是,因为unordered_map只能包含唯一键,所以您将看到常量时间的平均复杂度(容器首先检查哈希索引,然后迭代该索引处的值)。
我认为unordered_map::count功能的文档内容更丰富:
在容器中搜索键为k的元素并返回 找到的元素数量。因为unordered_map容器没有 允许重复键,这意味着实际的功能 如果容器中存在具有该键的元素,则返回1 否则为零。