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.Queue | queue.SimpleQueue | collections.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()