【问题标题】:Time-complexity of checking if two frozensets are equal in Python在 Python 中检查两个冻结集是否相等的时间复杂度
【发布时间】:2025-12-15 20:15:01
【问题描述】:

在网上任何地方都找不到这方面的详细信息,当比较两个frozensets 时,Python 是遍历其中一个集合中的元素还是检查frozensets 的哈希值,因为frozensets 是可散列的?

【问题讨论】:

标签: python frozenset


【解决方案1】:

由于参考文档没有说明这一点,它依赖于实现,因此除了查看您正在使用的 Python 版本的源代码(在您的 CPython 发行版的 Objects/setobject.c 中)之外,没有任何答案.查看 Python 3.7.0 的源代码,答案是“也许”;-)

Equality 首先检查frozensets 的大小是否相同(len())。如果不是,则它们不能相等,因此立即返回 False

否则,如果哈希码已经被计算过,则会比较它们。如果它们已经被计算过,那么如果哈希码不相等,则立即返回False。否则会调用逐个元素的代码来检查一个是否是另一个的子集。

frozenset 的哈希码不是仅仅为了它而计算的 - 这将是一笔可能无法得到回报的费用。所以必须有东西强迫它。 freezesets 一开始的主要用例是允许集合的集合,并且在 that 上下文中,哈希码将被计算为将frozenset 添加到包含集合的正常部分。 C 级集实现包含一个槽,用于记录哈希是否计算以及何时计算,该槽初始化为 -1(一个保留值,表示内部“没有已知哈希码”)。

【讨论】:

    【解决方案2】:

    hash(x) == hash(y) 并不暗示x == y

    >>> help(hash)
    hash(...)
        hash(object) -> integer
    
        Return a hash value for the object.  Two objects with the same value have
        the same hash value.  The reverse is not necessarily true, but likely.
    

    所以要比较两个frozenset 值是否相等,您仍然需要检查两个集合的大小是否相同,然后检查一个中的每个元素是否也在另一个中。

    我把它作为练习留给有大量空闲时间的读者来寻找两个具有相同哈希值的不同frozensets。

    【讨论】:

    • 仅供参考,您可以通过使用整数 2**ii in range(300) 构建单例frozensets 来找到具有相同哈希码的一大堆:-)