跳到主要内容

队列

简介

基本的队列是一种先进先出的数据结构。

一般的队列基本操作如下:

  • create:创建空队列
  • add:将新数据加入队列的末尾。返回新队列。
  • delete:删除队列头部的数据,返回新队列。
  • fromt:返回队列头部的值
  • empty:若队列为空,则返回一个空队列。

python实现

class lqueue(self):
def __init__(self):
self.list = []

# 入队
def inq(self.item):
self.list.append(item)

# 出队
def outq(self):
self.list.pop(0)

# 判断是否为空
def is_empty(self):
return self.list == []

# 队列长度
def qlength(self):
return len(self.list)

Python内置队列

python的queue模块提供了一个先进先出的队列类型Queue。Queue主要有以下几种方法:

  • put():在队列尾部添加元素
  • get():从队列头部取出元素,返回队列头部元素
  • empty():判断队列是否为空
  • full():判断队列是否达到最大长度限制
  • qsize():队列当前长度
from queue import Queue

# maxsize=0表示不限制队列长度
q = Queue(maxsize=0)

q.put(1)
q.put(2)
print(q.queue) # deque([1, 2])

q.get() # 1
print(q.queue) # deque([2])
print(q.qsize()) # 1
print(q.empty()) # false
print(q.full()) # false

虽然queue.Queue()是纯正的队列类,但一般更推荐使用双向队列类 deque

from collections import deque

que: deque[int] = deque()

# 元素入队
que.append(1)
que.append(3)
que.append(2)
que.append(5)
que.append(4)

# 访问队首元素
front: int = que[0]

# 元素出队
pop: int = que.popleft()

# 获取队列的长度
size: int = len(que)

# 判断队列是否为空
is_empty: bool = len(que) == 0

双向队列

在队列中,我们仅能删除头部元素或在尾部添加元素。双向队列(double-ended queue)提供了更高的灵活性,允许在头部和尾部执行元素的添加或删除操作。

Python实现

class ListNode:
"""双向链表节点"""

def __init__(self, val: int):
"""构造方法"""
self.val: int = val
self.next: ListNode | None = None # 后继节点引用
self.prev: ListNode | None = None # 前驱节点引用

class LinkedListDeque:
"""基于双向链表实现的双向队列"""

def __init__(self):
"""构造方法"""
self._front: ListNode | None = None # 头节点 front
self._rear: ListNode | None = None # 尾节点 rear
self._size: int = 0 # 双向队列的长度

def size(self) -> int:
"""获取双向队列的长度"""
return self._size

def is_empty(self) -> bool:
"""判断双向队列是否为空"""
return self._size == 0

def push(self, num: int, is_front: bool):
"""入队操作"""
node = ListNode(num)
# 若链表为空,则令 front 和 rear 都指向 node
if self.is_empty():
self._front = self._rear = node
# 队首入队操作
elif is_front:
# 将 node 添加至链表头部
self._front.prev = node
node.next = self._front
self._front = node # 更新头节点
# 队尾入队操作
else:
# 将 node 添加至链表尾部
self._rear.next = node
node.prev = self._rear
self._rear = node # 更新尾节点
self._size += 1 # 更新队列长度

def push_first(self, num: int):
"""队首入队"""
self.push(num, True)

def push_last(self, num: int):
"""队尾入队"""
self.push(num, False)

def pop(self, is_front: bool) -> int:
"""出队操作"""
if self.is_empty():
raise IndexError("双向队列为空")
# 队首出队操作
if is_front:
val: int = self._front.val # 暂存头节点值
# 删除头节点
fnext: ListNode | None = self._front.next
if fnext is not None:
fnext.prev = None
self._front.next = None
self._front = fnext # 更新头节点
# 队尾出队操作
else:
val: int = self._rear.val # 暂存尾节点值
# 删除尾节点
rprev: ListNode | None = self._rear.prev
if rprev is not None:
rprev.next = None
self._rear.prev = None
self._rear = rprev # 更新尾节点
self._size -= 1 # 更新队列长度
return val

def pop_first(self) -> int:
"""队首出队"""
return self.pop(True)

def pop_last(self) -> int:
"""队尾出队"""
return self.pop(False)

def peek_first(self) -> int:
"""访问队首元素"""
if self.is_empty():
raise IndexError("双向队列为空")
return self._front.val

def peek_last(self) -> int:
"""访问队尾元素"""
if self.is_empty():
raise IndexError("双向队列为空")
return self._rear.val

def to_array(self) -> list[int]:
"""返回数组用于打印"""
node = self._front
res = [0] * self.size()
for i in range(self.size()):
res[i] = node.val
node = node.next
return res

使用python内置库deque

from collections import deque

# 初始化双向队列
deq: deque[int] = deque()

# 元素入队
deq.append(2) # 添加至队尾
deq.append(5)
deq.append(4)
deq.appendleft(3) # 添加至队首
deq.appendleft(1)

# 访问元素
front: int = deq[0] # 队首元素
rear: int = deq[-1] # 队尾元素

# 元素出队
pop_front: int = deq.popleft() # 队首元素出队
pop_rear: int = deq.pop() # 队尾元素出队

# 获取双向队列的长度
size: int = len(deq)

# 判断双向队列是否为空
is_empty: bool = len(deq) == 0