数据结构-队列
队列概念
队列 Queue是一个数据集合,仅允许在列表一端插入,另一端进行删除
进行插入的一端称为队尾(rear),插入动作称为进队或入队
进行删除的一端称为队头(front),删除动作称为出队
队列的性质:先进先出(First in,First out)
队列能不能用列表实现呢?
比较删除一个元素,列表操作的时间复杂度是O(n),这并不是我们所希望的
那如果维护两个指针,一个指向队头,一个指向队尾,当出队删除元素时,我们只要移动队头指针就可以了,那是不是就解决了上面的问题了,似乎是解决了,但是又引出另外一个问题,就删除元素的空间是还在的,这样会很浪费空间的,那怎么充分利用这空间呢,或者说,怎么在进队时,使得进队的元素指向这些空间进行充分利用呢?
为了解决上面问题,就引出了环形队列
环形队列
环形队列满足下面条件:
- 队头(front)和队尾(rear)相等时,队列为空
- rear + 1 = front,队满,为了区分队空,留了一小块空间
- 实现环形队列使用取余模型
- 队首指针前进1:front = (front + 1) % MaxSize
- 队尾指针前进1:rear = (rear + 1) % MaxSize
- 队空:rear == front
- 队满: (rear + 1) % MaxSize == front
class Queue:
def __init__(self, size=100):
self.queue = [0 for _ in range(size)]
self.size = size
self.rear = 0 #队尾指针
self.front = 0 #队首指针
def push(self, element):
if not self.is_filled:
self.rear = (self.rear + 1) % self.size
self.queue[self.rear] = element
else:
raise IndexError("Queue is filled.")
def pop(self):
if not self.is_empty:
self.front = (self.front + 1) % self.size
return self.queue[self.front]
else:
raise IndexError("Queue is empty.")
@property
def is_empty(self):
return self.rear == self.front
@property
def is_filled(self):
return (self.rear + 1) % self.size == self.front
Python队列内置模块
- 双向队列: from collections import deque(一般构造数据结构用这个,保证线程安全,用import queue)
- 创建队列:queue = deque()
- 进队:append()
- 出队:popleft()
- 双向队列队首进队:appendleft()
- 双向队列队尾出队:pop()
其中deque,第一参数是指定初始队列值,而第二参数则是指定队列的长度,不过它在队满的情况下,会自动出队之前的值,利用这个特性我们可以实现linux命令tail取后几行操作
from collections import deque
def tail(n):
with open('test.txt', 'r') as f:
q = deque(f, n)
return q
for line in tail(5):
print(line, end="")
利用队列实现广度优先走迷宫
from collections import deque
maze = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 0, 1],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
dirs = [
lambda x, y: (x + 1, y),
lambda x, y: (x - 1, y),
lambda x, y: (x, y - 1),
lambda x, y: (x, y + 1)
]
def print_r(path):
curNode = path[-1]
realpath = []
while curNode[2] == -1:
realpath.append(curNode[0:2])
curNode = path[curNode[2]]
realpath.append(curNode[0:2]) # 起点
realpath.reverse()
for node in realpath:
print(node)
def maze_path_queue(x1, y1, x2, y2):
queue = deque()
queue.append((x1, y1, -1))
path = []
while len(queue) > 0:
curNode = queue.pop()
path.append(curNode)
if curNode[0] == x2 and curNode[1] == y2:
# 终点
print_r(path)
return True
for dir in dirs:
nextNode = dir(curNode[0], curNode[1])
if maze[nextNode[0]][nextNode[1]] == 0:
queue.append((nextNode[0], nextNode[1], len(path) - 1)) # 后续节点进队,记录哪个节点带他来的
maze[nextNode[0]][nextNode[1]] = 2 # 标记为已经走过
else:
print("没有路")
return False
maze_path_queue(1, 1, 8, 8)

浙公网安备 33010602011771号