一、队列
队列(Queue)是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。
队列性质:先进先出(First-in,First-out)
队列的基本操作:
入队(进队):插入动作。进行插入的一端称为队尾(rear)
出队:删除动作。进行删除的一端成为队头(front)
队列能否用列表简单实现,为什么?
答:简单的用列表来做,如图所示:
当元素出队时,没有用的空间会随着元素的出队而增加,空间开销会变得很大。这种实现方式,不好。简单的用列表来做做不到。
解决方法:把队列头尾连起来,变成循环队列,如图所示:
图一:是个空队列 (rear=front)
图二、三:入队(rear+1)%Maxsize
图四、五:出队(front+1)%Maxsize
注意:当front=11(最大长度)时,要想把front变回0,算法是(front+1)%Maxsize,且无论什么数,对最大长度取余最后都能算出相应位置。所以出队为(front+1)%Maxsize,而不是front+1。同理,入队也是。
图六:如果此时此刻在rear+1这个位置再加一个元素,队满,rear=front,这个时候就会导致我们分不清front=rear到底是队空还是队满,于是决定牺牲一小块空间(如上图空间5),这个时候(rear+1)%Maxsize==front 为队满
二、队列的实现
方法一:自己用代码写一个队列
class Queue():
# 初始化队列
def __init__(self, Maxsize=100):
self.queue = [0 for _ in range(Maxsize)]
self.Maxsize = Maxsize
self.rear = 0 # 队尾指针
self.front = 0 # 对首指针
# 入队
def push_queue(self, element):
self.rear = (self.rear + 1) % self.Maxsize
self.queue[self.rear] = element
# 出队 出队前提:栈不为空
def pop_queue(self):
if not self.is_empty():
self.front = (self.front + 1) % self.Maxsize
return self.queue[self.front]
else:
raise IndexError('Queue is empty')
# 空队列
def is_empty(self):
return self.rear == self.front
# 队列为空返回1,栈不为空返回0
# 队满
def is_filled(self):
return (self.rear + 1) % self.Maxsize == self.front
q = Queue(5)
for i in range(4): # 最后一个空间不用
q.push_queue(i)
print(q.is_filled())
print(q.pop_queue())
print(q.pop_queue())
print(q.pop_queue())
print(q.pop_queue())
输出:
True
0
1
2
3
方法二:直接用python中的collections模块中的deque方法实现
入队:deque.append(x)
出队:deque.popleft(x) #从列表左边弹出的意思(队列先进先出)
from collections import deque
def plan_one():
# 单向队列
queue = deque()
queue.append(1) # 整数1入队
queue.append(2) # 整数2入队
queue.popleft()
return queue # 该函数最后队列应只剩2
# 双向队列
# queue.appendleft(1) #队首进队
# queue.pop() #队尾出队
def plan_two():
queue = deque([1, 2, 3, 4, 5])
# 已经有1,2,3,4,5这五个整数在里边了
return queue
def plan_three():
queue = deque([1, 2, 3], 5) # 已有3个数,队列最大长度为54
return queue
print(plan_one())
print(plan_two())
print(plan_three())
输出为:
deque([2])
deque([1, 2, 3, 4, 5])
deque([1, 2, 3], maxlen=5)
注意:在函数plan_three中,如果队列长度满了,deque就会自动出队(出的第一个数)。