Skip to content

implementation

文件信息

  • 📄 原文件:implementation.py
  • 🔤 语言:python

栈和队列实现 包含栈、队列、循环队列、双端队列、单调栈等实现。

完整代码

python
from typing import TypeVar, Generic, List, Optional, Iterator
from collections import deque

T = TypeVar('T')


# ============================================================
#                    栈实现
# ============================================================

class Stack(Generic[T]):
    """
    栈实现(基于数组)

    时间复杂度:所有操作 O(1)
    """

    def __init__(self):
        self._data: List[T] = []

    def push(self, item: T) -> None:
        """入栈"""
        self._data.append(item)

    def pop(self) -> T:
        """出栈"""
        if self.is_empty():
            raise IndexError("栈为空")
        return self._data.pop()

    def peek(self) -> T:
        """查看栈顶"""
        if self.is_empty():
            raise IndexError("栈为空")
        return self._data[-1]

    def is_empty(self) -> bool:
        """是否为空"""
        return len(self._data) == 0

    def size(self) -> int:
        """元素数量"""
        return len(self._data)

    def __len__(self) -> int:
        return self.size()

    def __repr__(self) -> str:
        return f"Stack({self._data})"


class LinkedStack(Generic[T]):
    """
    栈实现(基于链表)

    时间复杂度:所有操作 O(1)
    """

    class Node:
        def __init__(self, val, next=None):
            self.val = val
            self.next = next

    def __init__(self):
        self._top: Optional[self.Node] = None
        self._size = 0

    def push(self, item: T) -> None:
        """入栈"""
        self._top = self.Node(item, self._top)
        self._size += 1

    def pop(self) -> T:
        """出栈"""
        if self.is_empty():
            raise IndexError("栈为空")
        val = self._top.val
        self._top = self._top.next
        self._size -= 1
        return val

    def peek(self) -> T:
        """查看栈顶"""
        if self.is_empty():
            raise IndexError("栈为空")
        return self._top.val

    def is_empty(self) -> bool:
        return self._size == 0

    def size(self) -> int:
        return self._size


class MinStack:
    """
    最小栈:支持 O(1) 获取最小值

    思路:使用辅助栈同步存储当前最小值
    """

    def __init__(self):
        self._data = []
        self._min_stack = []

    def push(self, val: int) -> None:
        self._data.append(val)
        # 如果当前值 <= 最小值,入辅助栈
        if not self._min_stack or val <= self._min_stack[-1]:
            self._min_stack.append(val)

    def pop(self) -> None:
        val = self._data.pop()
        # 如果弹出的是最小值,辅助栈也弹出
        if val == self._min_stack[-1]:
            self._min_stack.pop()

    def top(self) -> int:
        return self._data[-1]

    def get_min(self) -> int:
        return self._min_stack[-1]


# ============================================================
#                    队列实现
# ============================================================

class Queue(Generic[T]):
    """
    队列实现(基于 deque)

    时间复杂度:所有操作 O(1)
    """

    def __init__(self):
        self._data = deque()

    def enqueue(self, item: T) -> None:
        """入队"""
        self._data.append(item)

    def dequeue(self) -> T:
        """出队"""
        if self.is_empty():
            raise IndexError("队列为空")
        return self._data.popleft()

    def front(self) -> T:
        """查看队首"""
        if self.is_empty():
            raise IndexError("队列为空")
        return self._data[0]

    def rear(self) -> T:
        """查看队尾"""
        if self.is_empty():
            raise IndexError("队列为空")
        return self._data[-1]

    def is_empty(self) -> bool:
        return len(self._data) == 0

    def size(self) -> int:
        return len(self._data)

    def __len__(self) -> int:
        return self.size()

    def __repr__(self) -> str:
        return f"Queue({list(self._data)})"


class CircularQueue:
    """
    循环队列(基于数组)

    解决普通数组队列的"假溢出"问题
    """

    def __init__(self, capacity: int):
        # 多分配一个空间用于区分空和满
        self._capacity = capacity + 1
        self._data = [None] * self._capacity
        self._front = 0
        self._rear = 0

    def enqueue(self, item) -> bool:
        """入队,成功返回 True"""
        if self.is_full():
            return False
        self._data[self._rear] = item
        self._rear = (self._rear + 1) % self._capacity
        return True

    def dequeue(self):
        """出队"""
        if self.is_empty():
            raise IndexError("队列为空")
        item = self._data[self._front]
        self._front = (self._front + 1) % self._capacity
        return item

    def front(self):
        """查看队首"""
        if self.is_empty():
            raise IndexError("队列为空")
        return self._data[self._front]

    def rear(self):
        """查看队尾"""
        if self.is_empty():
            raise IndexError("队列为空")
        # 队尾指针的前一个位置
        return self._data[(self._rear - 1 + self._capacity) % self._capacity]

    def is_empty(self) -> bool:
        return self._front == self._rear

    def is_full(self) -> bool:
        return (self._rear + 1) % self._capacity == self._front

    def size(self) -> int:
        return (self._rear - self._front + self._capacity) % self._capacity

    def __repr__(self) -> str:
        if self.is_empty():
            return "CircularQueue([])"
        items = []
        i = self._front
        while i != self._rear:
            items.append(str(self._data[i]))
            i = (i + 1) % self._capacity
        return f"CircularQueue([{', '.join(items)}])"


class Deque(Generic[T]):
    """
    双端队列实现

    两端都可以进行插入和删除操作
    """

    def __init__(self):
        self._data = deque()

    def add_first(self, item: T) -> None:
        """头部添加"""
        self._data.appendleft(item)

    def add_last(self, item: T) -> None:
        """尾部添加"""
        self._data.append(item)

    def remove_first(self) -> T:
        """头部删除"""
        if self.is_empty():
            raise IndexError("双端队列为空")
        return self._data.popleft()

    def remove_last(self) -> T:
        """尾部删除"""
        if self.is_empty():
            raise IndexError("双端队列为空")
        return self._data.pop()

    def first(self) -> T:
        """查看头部"""
        if self.is_empty():
            raise IndexError("双端队列为空")
        return self._data[0]

    def last(self) -> T:
        """查看尾部"""
        if self.is_empty():
            raise IndexError("双端队列为空")
        return self._data[-1]

    def is_empty(self) -> bool:
        return len(self._data) == 0

    def size(self) -> int:
        return len(self._data)

    def __len__(self) -> int:
        return self.size()


# ============================================================
#                    用栈实现队列
# ============================================================

class QueueUsingStacks:
    """
    用两个栈实现队列

    思路:
    - inStack 负责入队
    - outStack 负责出队
    - 出队时如果 outStack 为空,将 inStack 倒入 outStack

    均摊时间复杂度:O(1)
    """

    def __init__(self):
        self._in_stack = []
        self._out_stack = []

    def push(self, x: int) -> None:
        """入队"""
        self._in_stack.append(x)

    def pop(self) -> int:
        """出队"""
        self._move_if_needed()
        return self._out_stack.pop()

    def peek(self) -> int:
        """查看队首"""
        self._move_if_needed()
        return self._out_stack[-1]

    def empty(self) -> bool:
        return not self._in_stack and not self._out_stack

    def _move_if_needed(self) -> None:
        """将 inStack 倒入 outStack"""
        if not self._out_stack:
            while self._in_stack:
                self._out_stack.append(self._in_stack.pop())


# ============================================================
#                    用队列实现栈
# ============================================================

class StackUsingQueue:
    """
    用一个队列实现栈

    思路:入栈时,将队列中已有元素依次出队再入队
    使新元素始终在队首
    """

    def __init__(self):
        self._queue = deque()

    def push(self, x: int) -> None:
        """入栈"""
        self._queue.append(x)
        # 将之前的元素移到后面
        for _ in range(len(self._queue) - 1):
            self._queue.append(self._queue.popleft())

    def pop(self) -> int:
        """出栈"""
        return self._queue.popleft()

    def top(self) -> int:
        """查看栈顶"""
        return self._queue[0]

    def empty(self) -> bool:
        return len(self._queue) == 0


# ============================================================
#                    单调栈
# ============================================================

class MonotonicStack:
    """
    单调栈示例:下一个更大元素

    对于数组中的每个元素,找到它右边第一个比它大的元素
    """

    @staticmethod
    def next_greater_element(nums: List[int]) -> List[int]:
        """
        下一个更大元素

        输入: [2, 1, 2, 4, 3]
        输出: [4, 2, 4, -1, -1]

        时间复杂度: O(n)
        空间复杂度: O(n)
        """
        n = len(nums)
        result = [-1] * n
        stack = []  # 存储索引

        for i in range(n):
            # 当前元素大于栈顶,说明找到了栈顶的下一个更大元素
            while stack and nums[i] > nums[stack[-1]]:
                idx = stack.pop()
                result[idx] = nums[i]
            stack.append(i)

        return result

    @staticmethod
    def daily_temperatures(temperatures: List[int]) -> List[int]:
        """
        每日温度:需要等待几天才能等到更暖和的一天

        输入: [73, 74, 75, 71, 69, 72, 76, 73]
        输出: [1, 1, 4, 2, 1, 1, 0, 0]

        时间复杂度: O(n)
        空间复杂度: O(n)
        """
        n = len(temperatures)
        result = [0] * n
        stack = []  # 存储索引

        for i in range(n):
            while stack and temperatures[i] > temperatures[stack[-1]]:
                idx = stack.pop()
                result[idx] = i - idx
            stack.append(i)

        return result

    @staticmethod
    def largest_rectangle_in_histogram(heights: List[int]) -> int:
        """
        柱状图中最大的矩形

        使用单调递增栈

        时间复杂度: O(n)
        空间复杂度: O(n)
        """
        stack = []  # 存储索引,对应高度单调递增
        max_area = 0
        heights = [0] + heights + [0]  # 添加哨兵

        for i, h in enumerate(heights):
            while stack and heights[stack[-1]] > h:
                height = heights[stack.pop()]
                width = i - stack[-1] - 1
                max_area = max(max_area, height * width)
            stack.append(i)

        return max_area


# ============================================================
#                    单调队列
# ============================================================

class MonotonicQueue:
    """
    单调队列示例:滑动窗口最大值
    """

    @staticmethod
    def max_sliding_window(nums: List[int], k: int) -> List[int]:
        """
        滑动窗口最大值

        输入: nums = [1,3,-1,-3,5,3,6,7], k = 3
        输出: [3,3,5,5,6,7]

        使用单调递减队列,队首始终是窗口最大值

        时间复杂度: O(n)
        空间复杂度: O(k)
        """
        if not nums or k == 0:
            return []

        result = []
        queue = deque()  # 存储索引,对应值单调递减

        for i, num in enumerate(nums):
            # 移除窗口外的元素
            while queue and queue[0] < i - k + 1:
                queue.popleft()

            # 保持单调递减:移除比当前元素小的
            while queue and nums[queue[-1]] < num:
                queue.pop()

            queue.append(i)

            # 窗口形成后开始记录结果
            if i >= k - 1:
                result.append(nums[queue[0]])

        return result


# ============================================================
#                    经典栈算法
# ============================================================

def is_valid_parentheses(s: str) -> bool:
    """
    有效的括号

    输入: "([{}])"
    输出: True

    时间复杂度: O(n)
    空间复杂度: O(n)
    """
    stack = []
    mapping = {')': '(', ']': '[', '}': '{'}

    for char in s:
        if char in mapping:
            # 右括号:检查是否匹配
            if not stack or stack.pop() != mapping[char]:
                return False
        else:
            # 左括号:入栈
            stack.append(char)

    return len(stack) == 0


def eval_rpn(tokens: List[str]) -> int:
    """
    逆波兰表达式求值(后缀表达式)

    输入: ["2", "1", "+", "3", "*"]
    输出: 9  ((2 + 1) * 3)

    时间复杂度: O(n)
    空间复杂度: O(n)
    """
    stack = []

    for token in tokens:
        if token in '+-*/':
            b = stack.pop()
            a = stack.pop()
            if token == '+':
                stack.append(a + b)
            elif token == '-':
                stack.append(a - b)
            elif token == '*':
                stack.append(a * b)
            else:
                # 注意:Python 的整除需要特殊处理负数
                stack.append(int(a / b))
        else:
            stack.append(int(token))

    return stack[0]


def decode_string(s: str) -> str:
    """
    字符串解码

    输入: "3[a2[c]]"
    输出: "accaccacc"

    时间复杂度: O(n)
    空间复杂度: O(n)
    """
    stack = []
    current_num = 0
    current_str = ""

    for char in s:
        if char.isdigit():
            current_num = current_num * 10 + int(char)
        elif char == '[':
            # 保存当前状态
            stack.append((current_str, current_num))
            current_str = ""
            current_num = 0
        elif char == ']':
            # 恢复并展开
            prev_str, num = stack.pop()
            current_str = prev_str + current_str * num
        else:
            current_str += char

    return current_str


# ============================================================
#                    测试代码
# ============================================================

if __name__ == "__main__":
    print("=" * 60)
    print("栈测试")
    print("=" * 60)

    stack = Stack()
    for i in [1, 2, 3, 4, 5]:
        stack.push(i)
    print(f"栈: {stack}")
    print(f"pop: {stack.pop()}, peek: {stack.peek()}")
    print(f"size: {stack.size()}, isEmpty: {stack.is_empty()}")

    print("\n--- 最小栈 ---")
    min_stack = MinStack()
    for val in [3, 5, 2, 1, 4]:
        min_stack.push(val)
        print(f"push {val}, min = {min_stack.get_min()}")

    print("\n" + "=" * 60)
    print("队列测试")
    print("=" * 60)

    queue = Queue()
    for i in [1, 2, 3, 4, 5]:
        queue.enqueue(i)
    print(f"队列: {queue}")
    print(f"dequeue: {queue.dequeue()}, front: {queue.front()}")

    print("\n--- 循环队列 ---")
    cq = CircularQueue(5)
    for i in [1, 2, 3, 4, 5]:
        cq.enqueue(i)
    print(f"循环队列: {cq}")
    cq.dequeue()
    cq.dequeue()
    cq.enqueue(6)
    print(f"出队两个后入队6: {cq}")

    print("\n" + "=" * 60)
    print("单调栈测试")
    print("=" * 60)

    nums = [2, 1, 2, 4, 3]
    print(f"数组: {nums}")
    print(f"下一个更大元素: {MonotonicStack.next_greater_element(nums)}")

    temps = [73, 74, 75, 71, 69, 72, 76, 73]
    print(f"\n温度: {temps}")
    print(f"每日温度: {MonotonicStack.daily_temperatures(temps)}")

    heights = [2, 1, 5, 6, 2, 3]
    print(f"\n柱状图: {heights}")
    print(f"最大矩形面积: {MonotonicStack.largest_rectangle_in_histogram(heights)}")

    print("\n" + "=" * 60)
    print("滑动窗口测试")
    print("=" * 60)

    nums = [1, 3, -1, -3, 5, 3, 6, 7]
    k = 3
    print(f"数组: {nums}, k = {k}")
    print(f"滑动窗口最大值: {MonotonicQueue.max_sliding_window(nums, k)}")

    print("\n" + "=" * 60)
    print("经典算法测试")
    print("=" * 60)

    print("\n--- 括号匹配 ---")
    tests = ["([{}])", "([)]", "((()))", ""]
    for s in tests:
        print(f"'{s}' -> {is_valid_parentheses(s)}")

    print("\n--- 逆波兰表达式 ---")
    tokens = ["2", "1", "+", "3", "*"]
    print(f"{tokens} = {eval_rpn(tokens)}")

    print("\n--- 字符串解码 ---")
    s = "3[a2[c]]"
    print(f"'{s}' -> '{decode_string(s)}'")

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布