krahets/hello-algo · error · IndexError

双向队列为空

Error message

双向队列为空

What it means

IndexError '双向队列为空' (deque is empty) raised by ArrayDeque.peek_first. Reading the front slot of an empty circular deque would return stale memory, so the guard refuses the operation. pop_first also routes through peek_first and inherits the failure.

Source

Thrown at codes/python/chapter_stack_and_queue/array_deque.py:76

    def pop_first(self) -> int:
        """队首出队"""
        num = self.peek_first()
        # 队首指针向后移动一位
        self._front = self.index(self._front + 1)
        self._size -= 1
        return num

    def pop_last(self) -> int:
        """队尾出队"""
        num = self.peek_last()
        self._size -= 1
        return num

    def peek_first(self) -> int:
        """访问队首元素"""
        if self.is_empty():
            raise IndexError("双向队列为空")
        return self._nums[self._front]

    def peek_last(self) -> int:
        """访问队尾元素"""
        if self.is_empty():
            raise IndexError("双向队列为空")
        # 计算尾元素索引
        last = self.index(self._front + self._size - 1)
        return self._nums[last]

    def to_array(self) -> list[int]:
        """返回数组用于打印"""
        # 仅转换有效长度范围内的列表元素
        res = []
        for i in range(self._size):
            res.append(self._nums[self.index(self._front + i)])
        return res

View on GitHub (pinned to 69932aed18)

Solutions

  1. Call is_empty() before peek_first or pop_first.
  2. When popping, prefer: val = dq.peek_first() if not dq.is_empty() else default.
  3. Reset or recreate the deque if its lifetime spans multiple drain phases.

Example fix

// before
head = dq.peek_first()  # raises if drained
// after
head = dq.peek_first() if not dq.is_empty() else None
Defensive patterns

Strategy: validation

Validate before calling

def safe_peek_first(dq):
    return dq.peek_first() if not dq.is_empty() else None

Type guard

def deque_non_empty(dq) -> bool:
    return not dq.is_empty()

Try / catch

try:
    head = dq.peek_first()
except IndexError:
    head = None

Prevention

When it happens

Trigger: Calling deque.peek_first() or deque.pop_first() when _size == 0.

Common situations: BFS or sliding-window code that pops without a length check; mixing peek_first and pop_first where the peek is assumed to always succeed; reusing a deque after draining it.

Related errors


AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13). Data as JSON: /api/errors/0652b4a80caba052. Report an issue: GitHub.