Queue
队列是一种先入先出 (First In, First Out, FIFO) 的线性数据结构。在实际应用中,队列被广泛用于各种场景,比如 BFS (宽度优先搜索)、处理请求等。在这篇博客中,我们将探索队列的基本概念、操作和应用。
基本概念
以下是队列的常用操作及其时间复杂度:
push(): 元素入队,即将元素添加至队尾。
pop(): 队首元素出队。
peek(): 访问队首元素,但不移除。
在 Python 中,可以使用 collections.deque 作为队列。虽然 Python 还提供了一个 queue.Queue() 类,但它主要用于多线程编程,所以在这里我们使用 collections.deque。
队列基础和基于链表的实现
队列是一种遵循先入先出原则的数据结构,我们可以用链表来实现它。我们将链表的一端作为队首,另一端作为队尾。
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next
class LinkedListQueue: def __init__(self): self.front = None self.rear = None self.size = 0 def push(self, x): node = ListNode(x) if not self.rear: self.front = self.rear = node else: self.rear.next = node self.rear = node self.size += 1 def pop(self): if not self.front: return None val = self.front.val self.front = self.front.next if not self.front: self.rear = None self.size -= 1 return val def peek(self): return self.front.val if self.front else None def is_empty(self): return self.size == 0
|
基于数组的实现
虽然链表是实现队列的一种方式,但我们也可以用数组来实现。使用数组时,需要处理数组的开始和结束位置,避免空间的浪费。
class ArrayQueue: def __init__(self, capacity): self.data = [None] * capacity self.front = 0 self.size = 0 def push(self, x): if self.size == len(self.data): raise ValueError("Queue is full") rear = (self.front + self.size) % len(self.data) self.data[rear] = x self.size += 1 def pop(self): if self.size == 0: raise ValueError("Queue is empty") val = self.data[self.front] self.data[self.front] = None self.front = (self.front + 1) % len(self.data) self.size -= 1 return val def peek(self): if self.size == 0: raise ValueError("Queue is empty") return self.data[self.front] def is_empty(self): return self.size == 0
|
使用栈实现队列
由于栈是一种后入先出 (Last In, First Out, LIFO) 的数据结构,我们可以使用两个栈来模拟队列的行为。一个栈用于入队,另一个栈用于出队。
class MyQueue: def __init__(self): self.in_stack = [] self.out_stack = [] def push(self, x): self.in_stack.append(x) def pop(self): self._move() return self.out_stack.pop() def peek(self): self._move() return self.out_stack[-1] def _move(self): if not self.out_stack: while self.in_stack: self.out_stack.append(self.in_stack.pop()) def is_empty(self): return not self.in_stack and not self.out_stack
|
队列的应用 - BFS 和层次遍历
在 BFS(宽度优先搜索)中,队列用于按层次顺序遍历图或树的节点。当访问一个节点时,将其邻居节点添加到队列的尾部。之后,我们从队列的头部移除并处理节点。
class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right
def level_order(root): if not root: return [] result = [] queue = [root] while queue: level = [] for i in range(len(queue)): node = queue.pop(0) level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level) return result
|
队列在矩阵中的应用
在一个由 0 和 1 组成的矩阵中,我们可以使用 BFS 来计算每个元素到最近的 0 的距离。我们从每个 0 的位置开始,以层次遍历的方式,计算每个元素到 0 的最短距离。
def update_matrix(matrix): rows, cols = len(matrix), len(matrix[0]) queue = [] directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] for i in range(rows): for j in range(cols): if matrix[i][j] == 0: queue.append((i, j)) else: matrix[i][j] = float('inf') while queue: i, j = queue.pop(0) for dx, dy in directions: ni, nj = i + dx, j + dy if 0 <= ni < rows and 0 <= nj < cols and matrix[ni][nj] > matrix[i][j] + 1: matrix[ni][nj] = matrix[i][j] + 1 queue.append((ni, nj)) return matrix
|
总结
队列是一种非常实用的数据结构,它在多种场景中都能派上用场,例如 BFS 搜索、操作系统的任务调度等。在 Python 中,我们可以轻松地使用 collections.deque 或自定义数据结构来实现队列。通过学习和理解队列的基础知识和应用,我们可以更好地解决各种实际问题。
希望本文对您理解队列的基础概念和应用有所帮助。如果您有任何疑问或建议,请随时留言。