Python 为什么使用哈希而不是测试真正的相等性?
我最近一直在研究Python的字典(我相信它们在其他语言中被称为关联数组),但对其键的一些限制感到困惑 首先,dict键必须是不可变的。当我查看其背后的逻辑时,答案是字典就像哈希表一样查找键的值,因此不可变键(如果它们可以哈希)可能会更改其哈希值,从而在检索值时造成问题 我很好地理解了为什么会这样,但我仍然有点困惑于使用哈希表的意义。如果您只是没有散列键并测试真正的相等性(假设以相同方式构造的对象比较相等),那么您可以通过使用两个列表复制字典的大部分功能,而不受此限制 所以,我想这才是我真正的问题——使用散列而不是相等查找值背后的原理是什么Python 为什么使用哈希而不是测试真正的相等性?,python,dictionary,hash,Python,Dictionary,Hash,我最近一直在研究Python的字典(我相信它们在其他语言中被称为关联数组),但对其键的一些限制感到困惑 首先,dict键必须是不可变的。当我查看其背后的逻辑时,答案是字典就像哈希表一样查找键的值,因此不可变键(如果它们可以哈希)可能会更改其哈希值,从而在检索值时造成问题 我很好地理解了为什么会这样,但我仍然有点困惑于使用哈希表的意义。如果您只是没有散列键并测试真正的相等性(假设以相同方式构造的对象比较相等),那么您可以通过使用两个列表复制字典的大部分功能,而不受此限制 所以,我想这才是我真正的问
如果非要我猜的话,很可能是因为比较整数的速度非常快,而且经过了优化,而比较其他类的实例的速度可能不快。您似乎忽略了哈希表的整个要点,它是快速(O(1))1检索的,没有哈希就无法实现,即,将键转换为某种分布均匀的整数,用作表的索引。请注意,在检索时仍然需要相等,以便能够处理哈希冲突2,但只有当您已经将元素集缩小到具有特定哈希的元素时,才能使用相等 只要相等,您就可以用并行数组或类似的东西复制类似的功能,但这将使检索成为O(n)3;如果您要求严格的弱排序,那么您可以实现RB树,它允许O(logn)检索。但是O(1)需要散列 请看一看,了解有关哈希表的更多信息
注释
通过使用hastables,您可以获得
O(1)
检索数据,而与每个独立值进行相等性比较时,将获得O(n)
(在顺序搜索中)或O(log(n))
(在二进制搜索中)
还要注意,
O(1)
是摊销时间,因为如果有多个值散列到同一个键,则需要在这些值之间进行顺序搜索。@FrédéricHamidi O(n log n)??你怎么知道的?即使对于R/B树,项访问也只是O(logn),如果它的时间复杂度为O(nlogn)@JoeC,那么使用哈希映射有什么意义呢,从内存:)我可能错了,我正在四处搜索以进行双重检查。我的坏,我能找到的最坏的情况是O(logn/logn)。我的观点是正确的。@FrédéricHamidi同样,O(n)比O(n log n)=>从你所说的列表比哈希表快:)@JoeC,是的,你是对的,我想知道我从哪里得到这种复杂性。看起来我把排序的复杂性搞混了。。。无论如何,现在我不会再犯同样的错误了:)@FrédéricHamidi:或多或少;在某些病理情况下,您可以得到O(n)(所有元素都得到相同的散列),但这就像是快速排序的最坏情况—在实践中不可能发生。RB检索是O(log(n))
而不是O(n*log(n))
。。。。否则它会比线性搜索更糟糕。即使有碰撞,它也是O(1)平均值。也就是说,使用分布良好的散列,您将获得每次访问的平均冲突数,例如1。有时会发生1次碰撞,有时2次,有时0次,有时甚至5次,但很少发生。因此,您平均需要2次尝试访问任何内容(1次冲突,1次重试)。是O(2)。O(2)与O(1)相同:O表示法忽略常数因子。