You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3实现LinkedList删除指定值所有节点时出现AttributeError问题排查

解决链表删除所有指定节点的AttributeError问题

看起来你在实现链表删除所有指定节点时遇到了典型的空指针问题,咱们一步步拆解问题并修复它。

首先,先梳理下你代码里的几个核心问题:

  1. 类结构混淆:你把LinkedList(链表)的方法(比如get_head_node、insert_beginning)放到了Node(节点)类里,这是结构错误——节点只需要管理自身的值和下一个节点的引用,而链表才需要负责管理头节点、插入、删除等整体操作。
  2. 缺少必要方法:你的Node类里没有定义set_next_node和get_next_node方法,但代码里却调用了它们,这会导致运行报错。
  3. 删除逻辑的缺陷:
    • 用stringify_list().count()来确定删除次数的方式不可靠,删除过程中链表结构会变化,很容易导致重复处理或漏处理。
    • 在删除中间节点时,找到目标节点后你直接把current_node = None退出循环,这会导致后续的目标节点无法被处理;更关键的是,你没有判断next_node是否为None就直接调用next_node.get_value(),这就是触发AttributeError的直接原因——当遍历到链表最后一个节点时,next_node是None,调用它的get_value()自然会报错。

接下来,咱们重构代码,先把Node和LinkedList类分开,然后修复删除逻辑:

修正后的完整代码

class Node:
    def __init__(self, value, next_node=None):
        self.value = value
        self.next_node = next_node
    
    def get_value(self):
        return self.value
    
    def get_next_node(self):
        return self.next_node
    
    def set_next_node(self, next_node):
        self.next_node = next_node

class LinkedList:
    def __init__(self, head_node=None):
        self.head_node = head_node
    
    def get_head_node(self):
        return self.head_node
    
    def insert_beginning(self, new_value):
        new_node = Node(new_value)
        new_node.set_next_node(self.head_node)
        self.head_node = new_node
    
    def stringify_list(self):
        string_list = ""
        current_node = self.get_head_node()
        while current_node:
            string_list += str(current_node.get_value()) + "\n"
            current_node = current_node.get_next_node()
        return string_list
    
    def remove_all_node(self, value_to_remove):
        # 先处理头节点:如果头节点是目标值,一直更新头节点直到不是目标值
        while self.head_node and self.head_node.get_value() == value_to_remove:
            self.head_node = self.head_node.get_next_node()
        
        # 如果处理后头节点为空,直接返回
        if not self.head_node:
            return
        
        # 处理中间和尾部节点
        current_node = self.head_node
        while current_node.get_next_node():
            if current_node.get_next_node().get_value() == value_to_remove:
                # 跳过目标节点
                current_node.set_next_node(current_node.get_next_node().get_next_node())
            else:
                # 只有当前节点的下一个不是目标时,才移动到下一个节点
                current_node = current_node.get_next_node()

关键修复点解释

  1. 拆分类结构:把节点和链表的职责分开,Node只负责自身的属性和访问/修改方法,LinkedList负责管理整个链表的操作,逻辑更清晰。
  2. 循环处理头节点:因为头节点没有前驱,所以单独循环处理——只要头节点是目标值,就将头节点替换为下一个节点,直到头节点不是目标或链表为空。
  3. 安全遍历中间节点:遍历过程中先判断current_node.get_next_node()是否存在,再调用它的get_value(),避免空指针错误;而且在删除节点后,不移动current_node,因为新的下一个节点可能还是目标值(比如连续的目标节点),这样能一次性处理所有连续的目标节点。
  4. 去掉不可靠的count逻辑:直接通过一次遍历完成所有删除操作,更高效也更可靠。

测试示例

你可以用下面的代码测试修复后的方法:

# 创建链表并插入节点
ll = LinkedList()
ll.insert_beginning(3)
ll.insert_beginning(2)
ll.insert_beginning(3)
ll.insert_beginning(1)
ll.insert_beginning(3)

print("删除前的链表:")
print(ll.stringify_list())

ll.remove_all_node(3)

print("删除后的链表:")
print(ll.stringify_list())

运行后会输出:

删除前的链表:
3
1
3
2
3

删除后的链表:
1
2

内容的提问来源于stack exchange,提问作者iamcuriouscat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 17:54:07