Python线性探测哈希表__setitem__中碰撞与探测长度统计问题
线性探测哈希表的碰撞统计问题解析
嘿,我来帮你梳理下这个线性探测哈希表的碰撞统计问题~ 先从你最困惑的「统计变量始终为0」说起,再指出代码里的逻辑小问题:
一、统计变量始终为0的可能原因
1. 测试用例未触发碰撞场景
你定义的碰撞是两个不同key哈希到同一位置,如果你的测试数据满足以下任意一种情况,自然不会触发统计变量累加:
- 所有key的哈希值完全不重复;
- 插入的都是同一个key(执行更新操作,不会触发碰撞计数)。
你可以试试这个测试用例验证:
my_table = HashTable(size=5) # 假设这两个key的哈希值会冲突(比如用简单哈希函数的话大概率会) my_table["apple"] = "red" my_table["apply"] = "green" print(my_table.collision) # 正常应该返回1 print(my_table.totalProbeLength) # 正常应该返回1
2. 哈希函数(hash_value)实现问题
如果你的hash_value方法计算的位置永远不会重复(比如哈希函数过于分散,或者实现时出现错误),那也不会产生碰撞。你可以检查下hash_value的实现,比如用最基础的取模逻辑:
def hash_value(self, key): return hash(key) % self.table_size
这个实现会让不同key有概率哈希到同一位置,能触发碰撞统计。
3. 实例变量访问错误
确认你是访问同一个哈希表实例的collision和totalProbeLength,而不是每次操作后重新创建了新实例。比如下面的错误写法会导致统计永远为0:
# 错误示例:每次打印前都新建实例,统计被重置 my_table = HashTable() my_table["a"] = 1 my_table = HashTable() # 新建了一个空实例 print(my_table.collision) # 输出0
二、代码里的逻辑优化点
即使触发了碰撞,你的统计逻辑还有可以简化和修正的地方:
1. 冗余的sameKeyCollision变量
你可以去掉这个变量,用一个简单的collided标记位来区分是否已经计数过碰撞,逻辑会更清晰:
def __setitem__(self, key, value): position = self.hash_value(key) collided = False # 标记是否已统计过本次插入的碰撞 for _ in range(self.table_size): if self.array[position] is None: self.array[position] = (key, value) self.count += 1 return elif self.array[position][0] == key: self.array[position] = (key, value) # 更新值,无碰撞 return else: # 位置被占用且不是当前key if not collided: self.collision += 1 collided = True self.totalProbeLength += 1 position = (position + 1) % self.table_size raise ValueError("Table is Full!")
2. 探测长度的计数逻辑对齐定义
根据你的定义「后续解决冲突的尝试次数为探测长度」,先计数探测次数再移动位置,逻辑会更贴合你对探测长度的描述(原代码结果数值没问题,但顺序可以更直观)。
三、验证测试建议
你可以写一个简单的测试函数来验证统计功能:
def test_hash_table(): ht = HashTable(size=3) # 插入3个会连续碰撞的key ht["a"] = 1 ht["b"] = 2 ht["c"] = 3 print(f"碰撞次数:{ht.collision}") # 预期输出2(b和c都与a碰撞) print(f"总探测长度:{ht.totalProbeLength}") # 预期输出3(b探测1次,c探测2次) # 测试更新操作,不触发碰撞 ht["a"] = 100 print(f"更新后碰撞次数:{ht.collision}") # 预期仍为2 test_hash_table()
内容的提问来源于stack exchange,提问作者Sook Lim
相关产品推荐
相关产品推荐

