krahets/hello-algo · error · Error

堆疊為空

Error message

堆疊為空

What it means

An Error '堆疊為空' ('stack is empty') thrown by pop() in LinkedListStack (linkedlist_stack.ts:39). pop() first calls peek() (which is guarded), then advances stackPeek to stackPeek.next; the `if (!this.stackPeek)` check blocks unlinking the head of an empty list, preventing a null dereference when reading .next on null.

Source

Thrown at zh-hant/codes/typescript/chapter_stack_and_queue/linkedlist_stack.ts:39

    }

    /* 判斷堆疊是否為空 */
    isEmpty(): boolean {
        return this.size === 0;
    }

    /* 入堆疊 */
    push(num: number): void {
        const node = new ListNode(num);
        node.next = this.stackPeek;
        this.stackPeek = node;
        this.stkSize++;
    }

    /* 出堆疊 */
    pop(): number {
        const num = this.peek();
        if (!this.stackPeek) throw new Error('堆疊為空');
        this.stackPeek = this.stackPeek.next;
        this.stkSize--;
        return num;
    }

    /* 訪問堆疊頂元素 */
    peek(): number {
        if (!this.stackPeek) throw new Error('堆疊為空');
        return this.stackPeek.val;
    }

    /* 將鏈結串列轉化為 Array 並返回 */
    toArray(): number[] {
        let node = this.stackPeek;
        const res = new Array<number>(this.size);
        for (let i = res.length - 1; i >= 0; i--) {
            res[i] = node!.val;
            node = node!.next;

View on GitHub (pinned to 69932aed18)

Solutions

  1. Check stack.isEmpty() (or stkSize === 0) before pop.
  2. Drain with `while (!stack.isEmpty())`.
  3. Track pushes and never pop more than that.
  4. Return an optional from a wrapper when empty is a normal outcome.

Example fix

// before: popping an empty linked-list stack throws
const top = stack.pop();

// after: guard first
if (!stack.isEmpty()) {
    const top = stack.pop();
}
Defensive patterns

Strategy: validation

Validate before calling

// Guard LinkedListStack pop
function safePop(stack: LinkedListStack): number | undefined {
    return stack.isEmpty() ? undefined : stack.pop();
}
while (!stack.isEmpty()) {
    const top = stack.pop();
}

Type guard

const nonEmpty = (stack: LinkedListStack): boolean => !stack.isEmpty();

Try / catch

try {
    const top = stack.pop();
} catch (e) {
    if (e instanceof Error && e.message === '堆疊為空') {
        // stack empty; handle gracefully
    } else throw e;
}

Prevention

When it happens

Trigger: Calling stack.pop() when this.stackPeek is null (stkSize === 0). Popping more than you pushed, or popping a freshly constructed `new LinkedListStack()`.

Common situations: Unbalanced push/pop in expression evaluation or backtracking; popping after a previous pop emptied the stack; DFS that pops on backtrack without checking depth; reusing a stack instance across runs without resetting state.

Related errors


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