【代码随想录】d10-栈与队列-part01-python

1.理论基础

1.1队列

1.1.1队列定义

  • 队列(Queue)是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。
  • 队列性质:先进先出(First-in,First-out)
  • 队列的基本操作:
    • 入队(进队):插入动作。进行插入的一端称为队尾(rear)
    • 出队:删除动作。进行删除的一端成为队头(front)

1.1.2在python中队列数据结构

在Python中,queue.Queue、queue.SimpleQueue 和 collections.deque 都可以用于实现队列数据结构,但它们在使用方法和性能上有一些不同。

  • queue.Queue:
    • 这是 Python 标准库中的队列实现。它是线程安全的,支持多个生产者和消费者。它提供了常用的队列操作方法,如 put()(将元素放入队列)、get()(从队列中取出元素)、empty()(判断队列是否为空)等。
  • queue.SimpleQueue:
    • 这是 Python 3.7+ 版本中新增的队列实现。与 queue.Queue 相比,它更简单,但不支持多个生产者和消费者。它提供了与 queue.Queue 类似的操作方法。
  • collections.deque:
    • deque 是双端队列(double-ended queue)的缩写。它提供了在队列两端进行快速插入和删除操作的能力。deque 可以用作普通队列,也可以用作栈(先进后出)或双向队列。

这些队列的选择取决于具体需求。如果需要线程安全且支持多个生产者和消费者的队列,可以使用 queue.Queue。如果只需要一个生产者和一个消费者的简单队列,可以使用 queue.SimpleQueue。如果需要快速在队列两端执行插入和删除操作,可以使用 collections.deque。

1.1.3示例

queue.Queue 示例

import queue

# 创建一个队列
q = queue.Queue()

# 向队列中添加元素
q.put(1)
q.put(2)
q.put(3)

# 从队列中取出元素
item = q.get()
print(item)  # 输出:1

# 查看队列是否为空
is_empty = q.empty()
print(is_empty)  # 输出:False

queue.SimpleQueue 示例

import queue

# 创建一个简单队列
q = queue.SimpleQueue()

# 向队列中添加元素
q.put(1)
q.put(2)
q.put(3)

# 从队列中取出元素
item = q.get()
print(item)  # 输出:1

# 查看队列是否为空
is_empty = q.empty()
print(is_empty)  # 输出:False

collections.deque 示例

from collections import deque

# 创建一个双端队列
q = deque()

# 向队列中添加元素
q.append(1)
q.append(2)
q.append(3)

# 从队列左侧取出元素
left_item = q.popleft()
print(left_item)  # 输出:1

# 查看队列是否为空
is_empty = not bool(q)
print(is_empty)  # 输出:False

1.1.4对比

特性queue.Queuequeue.SimpleQueuecollections.deque
实现方式基于 threading 模块基于 queue 模块基于 collections 模块
多线程安全
添加元素put(item)put(item)append(item)
取出元素get()get()popleft()
查看队列是否为空empty()empty()not bool(deque)

queue.Queue 和 queue.SimpleQueue 是为多线程环境设计的,因此它们具有线程安全性,适用于多线程程序。而 collections.deque 不是线程安全的,因此在多线程环境中需要手动进行同步控制。此外,collections.deque 在性能上可能更快,因为它是基于双端队列实现的,而不涉及线程同步。

1.2栈

1.2.1栈的定义

栈(Stack)是一种常见的数据结构,它遵循后进先出(Last-In, First-Out,LIFO)的原则,类似于现实生活中的一堆盘子,你只能在顶部放置或移除盘子。在计算机科学中,栈通常用于管理函数调用、表达式求值、内存管理等各种任务。让我们首先进行理论介绍,然后提供Python中栈的实际实现和使用方式的示例。

1.2.2栈的基本操作

  • push(item): 将元素压入栈顶。
  • pop(): 弹出栈顶元素。
  • top(): 返回栈顶元素,但不弹出。
  • is_empty(): 检查栈是否为空。
  • size(): 返回栈中元素的数量。

在Python中,可以使用列表(list)来实现栈,因为列表支持append()(用于入栈)和pop()(用于出栈)操作

1.2.3使用列表实现栈

class Stack:
    def __init__(self):
        self.items = []

    def is_empty(self):
        return len(self.items) == 0

    def push(self, item):
        self.items.append(item)

    def pop(self):
        if not self.is_empty():
            return self.items.pop()
        else:
            raise IndexError("Pop from an empty stack")

    def top(self):
        if not self.is_empty():
            return self.items[-1]
        else:
            raise IndexError("Top on an empty stack")

    def size(self):
        return len(self.items)

# 创建一个栈
stack = Stack()

# 入栈操作
stack.push(1)
stack.push(2)
stack.push(3)

# 出栈操作
popped_item = stack.pop()
print(f"Popped item: {popped_item}")

# 查看栈顶元素
top_item = stack.top()
print(f"Top item: {top_item}")

# 检查栈是否为空
print(f"Is stack empty? {stack.is_empty()}")

# 查看栈的大小
print(f"Stack size: {stack.size()}")

2. 232.用栈实现队列

2.1题目及讲解

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false
    说明:
  • 你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

题目链接/文章讲解/视频讲解:https://programmercarl.com/0232.%E7%94%A8%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97.html

2.2代码实现

class MyQueue:

    def __init__(self):
        self.stack_in=[]
        self.stack_out = []

    def push(self, x: int) -> None:
        self.stack_in.append(x)

    def pop(self) -> int:
        if self.empty():
            return None
        if self.stack_out:
            return self.stack_out.pop()
        else:
            for i in range(len(self.stack_in)):
                # 要全部加进出栈列表后再去删除
                self.stack_out.append(self.stack_in.pop())
                # #入栈列表先删除元素
                # self.stack_in.pop()
                # #保存删除的元素
                # res = self.stack_in.pop()
                # #将删除的元素加到出栈中
                # self.stack_out.append(res)
                # #从出栈列表中再次删除
                # return self.stack_out.pop()
            return self.stack_out.pop()
            
    def peek(self) -> int:
        # 要求返回队列第一个元素,但是不删除这个元素,pop删除后会返回删除的元素,那么直接调用pop返回删除的元素后,再把元素重新加回去
        res = self.pop()
        self.stack_out.append(res)
        return res
        
    def empty(self) -> bool:
        # 出栈列表和入栈列表都不为空,表示队列不为空
        return not (self.stack_in or self.stack_out)

3. 225. 用队列实现栈

3.1题目及讲解

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
    -int top() 返回栈顶元素。
    -boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
    注意:
  • 你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

题目链接/文章讲解/视频讲解:https://programmercarl.com/0225.%E7%94%A8%E9%98%9F%E5%88%97%E5%AE%9E%E7%8E%B0%E6%A0%88.html

3.2代码实现

from collections import deque
# import queue
class MyStack:

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

    def push(self, x: int) -> None:
        self.queue.append(x)

    def pop(self) -> int:
        if self.empty():
            return None
        for i in range(len(self.queue)-1):
            self.queue.append(self.queue.popleft())
        return self.queue.popleft()

    def top(self) -> int:
        if self.empty():
            return None
        return self.queue[-1]

    def empty(self) -> bool:
        return not self.queue

# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值