Python中通过集合长度判断删除双向链表重复节点为何失效?
问题根因
你的去重逻辑存在两个核心问题,导致功能无法正常生效:
- 判断重复的维度错误:往集合
seen中添加的是Node类的实例对象,而非节点存储的实际业务数据。Python中自定义类的实例默认按内存地址做哈希校验,哪怕两个节点的data值完全相同,只要是独立创建的不同对象,就会被判定为非重复元素,集合长度会随遍历持续增长,你写的重复判断分支永远不会触发。 - 遍历链路中断:你通过
temp = cur想暂存节点以保留后续遍历位置,但Python对象是引用传递,temp和cur指向同一个内存地址的节点。而你的delete_node方法在删除节点时,会主动将待删除节点的next、prev指针置空,删除操作执行完成后temp.next也会变为None,直接导致遍历提前终止,无法访问链表后续节点。
修正方案
你的delete_node方法、节点类、链表基础方法逻辑均正常,仅需修改remove_duplicates方法即可,修正后代码如下:
def remove_duplicates(self): cur = self.head seen = set() while cur: # 提前存储下一个遍历节点,避免当前节点指针被修改后丢失遍历位置 next_node = cur.next if cur.data in seen: # 命中重复规则,删除当前节点 self.delete_node(cur) else: # 非重复数据加入已见集合 seen.add(cur.data) # 移动到提前存好的下一个节点 cur = next_node
逻辑说明
- 不再通过计算集合长度变化判断重复,直接用
in关键字判断数据是否已存在,写法更简洁,判断效率为O(1)。 - 在对当前节点做任何修改操作前,就提前把下一个要遍历的节点引用存到
next_node中,不管后续当前节点的指针怎么被修改,都不会影响遍历链路,能完整走完整个链表。
测试验证
可以用以下用例验证效果:
if __name__ == "__main__": dll = DoublyLinkedList() test_data = [1,2,3,2,1,4,3] for val in test_data: dll.append(val) print("去重前链表元素:") dll.print_list() dll.remove_duplicates() print("去重后链表元素:") dll.print_list()
运行后输出符合预期,会保留第一次出现的节点,删除后续所有值重复的节点,最终输出为1、2、3、4。
内容的提问来源于stack exchange,提问作者JyZ
相关产品推荐
相关产品推荐

