您的位置:首页 > 编程语言 > Python开发

python中的队列使用

2022-03-11 15:40 1001 查看

一、python队列在数据结构算法类应用:

Python标准库中包含了四种队列,分别是queue.Queue / asyncio.Queue / multiprocessing.Queue / collections.deque

Python的Queue模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。

还有一种常用,也是我觉得最好用的是deque,双边队列

相比于list实现的队列,deque实现拥有更低的时间和空间复杂度。list实现在出队(pop)和插入(insert)时的空间复杂度大约为O(n),deque在出队(pop)和入队(append)时的时间复杂度是O(1)。

所以deque更有优越性 而且deque既可以表示队列 又可以表示栈 实在是太方便了。

除了C、java中常见的函数外,支持in操作符、rotate(1)、rotate(-1)、copy()、extend()、extendleft()、index()、insert()、remove()、reverse。

举个例子:

调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。

示例:

输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。

双端队列的做法:

class Solution:
def exchange(self, nums: List[int]) -> List[int]:
tmp = collections.deque()
for num in nums:
tmp.appendleft(num) if num % 2 ==1 else tmp.append(num)
return list(tmp)

再举个实现单调队列的例子:

请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。

若队列为空,pop_front 和 max_value 需要返回 -1

示例 1:
输入:
["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
输出: [null,null,null,2,1,2]

示例 2:
输入:
["MaxQueue","pop_front","max_value"]
[[],[],[]]
输出: [null,-1,-1]
#单调栈写法
#均摊时间复杂度是O(1)
import queue
class MaxQueue:

def __init__(self):
self.dq = queue.deque()
self.q = queue.Queue()

def max_value(self) -> int:
return self.dq[0] if self.dq else -1

def push_back(self, value: int) -> None:
while self.dq and self.dq[-1] < value:
self.dq.pop()
self.dq.append(value)
self.q.put(value)

def pop_front(self) -> int:
if self.q == []: return -1
ans = self.q.get()
if ans == self.dq[0]:
self.dq.popleft()
return ans

二、python队列在线程间交换数据应用

当我做单调队列的时候,遇到过一个问题:

import queue
q = queue.Queue()
if q:
ans = q.get()
print(ans)

这段程序结果竟然是死循环,或者说一直被阻塞(后来才知道)

这个问题和上面有点相似:Queue.get()默认的也是阻塞方式读取数据,队列为空时,不会抛出 except Queue.Empty ,而是进入阻塞直至超时。

想要解决这个问题,必须加上block=False 的参数

同理,Queue.put()默认有 block = True 和 timeout 两个参数。

如下代码的结果并不是10个A,而是会混杂B。

import Queue
q = Queue.Queue(10)
for i in range(10):
myData = 'A'
q.put(myData)
myData = 'B'

当 block = True 时,写入是阻塞式的,阻塞时间由 timeout 肯定。正由于阻塞,才致使了后来的赋值污染了处于阻塞状态的数据。Queue.put()方法加上 block=False 的参数,便可解决这个隐蔽的问题。但要注意,非阻塞方式写队列,当队列满时会抛出 exception Queue.Full 的异常。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: