在Python中,栈和队列可以使用列表(List)来实现,因为列表提供了在末尾进行添加append()
和弹出pop()
操作的高效方法。然而,这里有一些需要注意的事项:
- 栈的实现
栈是一种后进先出(Last In, First Out,LIFO)的数据结构。在Python中,可以使用列表的 append() 方法来在末尾添加元素,使用pop()
方法从末尾移除元素。Python中的列表可以方便地用作栈。
虽然在许多情况下,使用列表作为栈是非常方便的,但在某些需要高效的情况下,例如在频繁插入和删除操作的大型数据集合中,可能需要考虑使用 collections 模块中的 deque 类,它提供了 O(1) 复杂度的队列和栈操作。 - 队列的实现
表(List): 你可以使用列表的 append() 方法在队尾添加元素,使用pop(0)
方法在队头删除元素。然而,在列表的开头执行pop(0)
操作会导致所有后续元素的移动,因此可能不是最高效的方法,特别是对于大型队列。如果队列很大,而且频繁地在队头执行删除操作,可能需要考虑使用其他数据结构。
collections 模块中的 deque: collections 模块提供了 deque 类,它是一个双端队列的实现。deque 支持高效的队列操作,包括在两端进行元素的添加和删除。你可以使用append()
和popleft()
方法在队尾添加元素和在队头删除元素,它们的时间复杂度均为 O(1)。因此,对于大型队列和需要频繁操作队头的情况,使用 deque 可能更合适。
queue 模块中的 Queue: Python 的标准库中提供了 queue 模块,其中的 Queue 类是一个线程安全的队列实现。它支持多线程环境下的安全操作,提供了put()
和get()
方法用于入队和出队操作。Queue 类的实现基于 deque。
综上所述,对于一般情况下的队列操作,可以使用列表或者 collections 模块中的 deque。如果需要在多线程环境下操作队列,可以考虑使用 queue 模块中的 Queue 类。
232.用栈实现队列 - 🔗
讲解 - 🔗
💡刚开始没什么思路,后来看了一下文字解析稍微能自己写了。做题的时候发现list.pop()
方法是有返回值的,返回被移除的元素的值,并且原始列表被修改,移除了指定位置的元素。所以通常会有list.append(list.pop())
这种写法。可以直接将pop()
的返回值作为参数传递给list.append()
。
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.stack_out:
return self.stack_out.pop()
else:
for i in range(len(self.stack_in)):
self.stack_out.append(self.stack_in.pop()) #list.pop()会返回被pop的值
return self.stack_out.pop()
def peek(self) -> int:
tmp = self.pop()
self.stack_out.append(tmp)
return tmp
def empty(self) -> bool:
if self.stack_in or self.stack_out:
return False
else:
return True
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
最后一部分⬇️可以改写为return not (self.stack_in or self.stack_out)
def empty(self) -> bool:
if self.stack_in or self.stack_out:
return False
else:
return True
225. 用队列实现栈 - 🔗
讲解 - 🔗
💡在之前还不是特别明白这道题的意思的时候,我一直觉得这道题很简单,因为我想着直接用一个deque,不就可以同时实现先入先出和先入后出了吗?但是我没有考虑到是要用队列实现栈。也就是说deque只能使用append+popleft功能或者appendleft+pop功能,才能符合队列的先入先出。
方法一:一个deque
from collections import deque
class MyStack:
# 把deque当成一个单向列表,由于遵循先入先出原则
# 只能同时拥有append + popleft,或者append + pop
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
# 固定最后一个元素,将前面的所有元素按先入先出的顺序popleft再append到最后一个元素后面
# 于是最后一个元素就变成了第一个元素
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
for i in range(len(self.queue) - 1):
self.queue.append(self.queue.popleft())
tmp = self.queue.popleft()
self.queue.append(tmp)
return tmp
def empty(self) -> bool:
if self.queue:
return False
else:
return True
方法二:两个deque - 不同于用栈实现队列,另一个deque是用于备份的
from collections import deque
class MyStack:
# 把deque当成一个单向列表,由于遵循先入先出原则,只能同时拥有append + popleft,或者append + pop
def __init__(self):
self.queue = deque()
self.backup = deque()
def push(self, x: int) -> None:
self.queue.append(x)
def pop(self) -> int:
if self.empty():
return None
# 将先放入的元素移到backup备份
for i in range(len(self.queue) - 1):
self.backup.append(self.queue.popleft())
# 获取到要移出的元素
tmp = self.queue.popleft()
# 将备份里的元素按原有顺序重新放到队列里
for i in range(len(self.backup)):
self.queue.append(self.backup.popleft())
return tmp
def top(self) -> int:
if self.empty():
return None
# 将先放入的元素移到backup备份
for i in range(len(self.queue) - 1):
self.backup.append(self.queue.popleft())
# 获取到top元素
tmp = self.queue.popleft()
# 将备份里的元素按原有顺序重新放到队列里
for i in range(len(self.backup)):
self.queue.append(self.backup.popleft())
self.queue.append(tmp)
return tmp
def empty(self) -> bool:
if self.queue:
return False
else:
return True