队列
简介
基本的队列是一种先进先出的数据结构。
一般的队列基本操作如下:
- 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