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

双向链表Deque的drop_between函数Bug排查:无法删除起始位置节点

解决双向链表Deque的drop_between函数问题

我来帮你搞定这个drop_between函数的bug~先看看你现有代码里的几个核心问题,再给你一个简洁高效的修复方案。

现有代码的问题分析

你的drop_between函数主要有这几个逻辑错误:

  1. 索引对应完全错位:你初始化cur_index=0,但循环里先移动curr到下一个节点,再判断cur_index,导致实际处理的节点索引和你判断的cur_index差1。比如你要删除索引1的节点时,代码里判断的是cur_index=0,自然会漏掉起始节点的删除。
  2. 节点链接修改错误:last_node.next = curr.next.next和curr.next.next.prev = last_node.next这两行完全写错了——正确的双向链表删除逻辑应该是让前节点的next指向当前节点的next,同时让当前节点的next的prev指向前节点(如果存在的话),你这里直接跳过了一个节点,导致链接混乱。
  3. 未更新关键属性:删除节点后没有修改self.size,也没处理tail的更新(如果删除的是末尾节点的话),会导致链表状态不一致。
  4. 循环条件限制:while curr.next会漏掉最后一个节点的处理,而且逐个遍历删除的效率也不高。

修复后的解决方案

我建议先写一个辅助函数用来根据索引快速定位节点,然后直接通过修改首尾节点的链接来批量删除范围节点,这样逻辑更清晰,效率也更高:

class Node:
    """ Initialize empty node """
    def __init__(self, data, prev = None, next = None):
        self.data = data
        self.next = next
        self.prev = prev

class Deque:
    """ A double-ended queue """
    def __init__(self):
        """ Initializes an empty Deque """
        self.head = None
        self.tail = None
        self.size = 0

    def __len__(self):
        """ Computes the number of elements in the Deque
        :return: The size of the Deque """
        return self.size

    def push_front(self, e):
        """ Inserts an element at the front of the Deque
        :param e: An element to insert """
        new_head = Node(data = e, next = self.head)
        if len(self) == 0:
            self.tail = new_head
        if self.head:
            self.head.prev = new_head
        self.head = new_head
        self.size += 1

    def _get_node(self, index):
        """辅助函数:根据索引获取对应节点(内部使用)"""
        if index < 0 or index >= self.size:
            raise IndexError("Index out of range")
        curr = self.head
        for _ in range(index):
            curr = curr.next
        return curr

    def drop_between(self, start, end):
        """ Deletes elements from the Deque that within the range [start, end)
        :param start: indicates the first position of the range
        :param end: indicates the last position of the range(does not drop this element) """
        # 先处理所有非法边界情况
        if start < 0 or end > self.size or start >= end:
            raise IndexError("Invalid range for drop_between")
        if start == end:
            return  # 没有节点需要删除,直接返回

        # 获取要删除范围的首尾节点
        start_node = self._get_node(start)
        # 如果end等于链表长度,end_node就是None(超出最后一个节点)
        end_node = self._get_node(end) if end < self.size else None

        # 获取要删除范围的前一个节点
        prev_node = start_node.prev

        # 修改双向链接
        if prev_node:
            prev_node.next = end_node
        else:
            # 如果start是0,说明要从表头开始删,更新head为end_node
            self.head = end_node

        if end_node:
            end_node.prev = prev_node
        else:
            # 如果end是链表长度,说明要删到表尾,更新tail为prev_node
            self.tail = prev_node

        # 更新链表长度
        self.size -= (end - start)

    def listprint(self, node):
        """ Prints each element of the node front to back
        :param node: """
        while (node is not None):
            print(node.data)
            node = node.next

def main():
    D = Deque()
    for num in range(10):
        D.push_front(num)
    print("删除前的链表:")
    D.listprint(D.head)
    print("------")
    D.drop_between(4,7)
    print("删除后的链表:")
    D.listprint(D.head)

if __name__ == "__main__":
    main()

修复逻辑说明

  1. 辅助函数_get_node:快速根据索引定位节点,避免重复写遍历逻辑,也让代码更易读。
  2. 边界处理:完善了非法范围的判断,比如end不能超过链表长度,start不能大于等于end等。
  3. 批量删除逻辑:直接找到要删除范围的第一个节点start_node和范围结束的节点end_node,然后修改start_node的前驱节点和end_node的链接,一次性断开整个范围的节点,比逐个删除高效得多。
  4. 关键属性更新:修改了head、tail和size,保证链表状态始终一致。

测试你的示例:当调用drop_between(1,3)时,链表[0,1,2,3]会正确变成[0,3];主函数里调用drop_between(4,7)后,会删除索引4、5、6对应的节点(也就是数值4、5、6),输出结果是0、1、2、3、7、8、9,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:53:24