队列的python实现
定义
- 队列是一种基本的数据结构,与“栈”互为表亲关系,队列是由一系列对象组成的集合,这些元素的插入和删除遵循先入先出的原则,即元素可以任意时刻进入队列,但只有处在队列最前面的元素才能被删除。
队列的抽象数据类型
- 通常来说,队列的抽象数据类型定义了一系列对象组成的集合,其中元素的访问和删除被限制在队列的第一个元素,而元素的插入被限制在队列的尾部。
- 队列Q的抽象数据类型支持以下基本方法:
- Q.enqueue() : 支持在队列的尾部增加一个元素
- Q.dequeue() : 删除并返回队列的第一个元素,如果队列为空,则触发错误。
- Q.first() : 在不删除第一个元素的情况下返回队列的第一个元素,如果队列为空,则触发错误。
- Q.is_empty() : 判断队列是否为空队列,并返回结果。
- len(Q) : 返回队列的长度,即队列元素的个数。
基于数组的队列的实现
- 用python实现队列,最简单的做法是使用列表类修改一个适配器类,添加元素时在列表的末端加入,删除元素时通过pop(0)来删除队列的第一个元素。但是这样操作的效率很低,pop操作会对序列产生“洞”,pop()操作的调用总是处于最坏情况。
- 最佳的实现方式是通过循环使用数组。让队列的前端更趋向于列表的右端,而队列内的元素在底层数组的尾部“循环”。此时底层数组假定的长度N是大于队列中实际元素的个数。
- 取模操作是处理循环数组的理想操作。
python队列的实现方法
-
""" 本文代码用于以python实现队列结构 """ class Error(Exception): """ 自定义异常类的原因是避免空栈调用top()/pop()方法报错时的提示信息是列表类的异常信息 """ pass class Arrayqueue(object): DEFAULT_SIZE = 10 def __init__(self): """ _front表示队列第一个元素的索引; _size表示队列内元素的数目; _data是一个固定容量的列表实例 """ self._front = 0 self._size = 0 self._data = [None] * Arrayqueue.DEFAULT_SIZE def __len__(self): return self._size def is_empty(self): return self._size == 0 def is_full(self): return self._size == len(self._data) def first(self): return self._data[self._front] def enqueue(self, arg): if self.is_full(): raise Error("arrayqueue is full") end = (self._front + self._size) % len(self._data) self._data.insert(end, arg) self._size += 1 def dequeue(self): if self.is_empty(): raise Error("arrayqueue is empty") first_index = self._front # 此处取模操作是为了第一位元素处于数组末端的情况 self._front = (self._front + 1) % len(self._data) self._data[first_index] = None self._size -= 1 if __name__ == "__main__": Q = Arrayqueue() Q.enqueue(1) Q.enqueue(2) print(len(Q)) print(Q.first()) Q.dequeue() print(Q.first())
注:第51行设为None的原因与python的回收未使用空间的机制有关,在内部python对已存的对象维护了一个对其的引用计数的计数器,如果计数器变为0,这个对象就无法访问,系统会回收这部分内存。对于离开队列的元素,队列已经不再负责它的存储,所以需要减少这个元素的引用计数。
基于单链表的队列的实现
-
由于需要对队列的两端进行操作,我们显式地为队列类Q维护两个实例变量
_head
和_tail
,队列的首元素和尾元素对映的是链表的头节点和尾节点。 -
# !/usr/bin/env python # -*-coding:utf-8 -*- """ # File : link_queue_of_python.py # Time :2022/1/10 15:10 # Author :kkk # version :python 3.6 # Description:本文件用于解释如何通过单链表实现队列 """ class Error(Exception): pass class LinkQueue(object): class Node(object): """ 定义节点类 element实例表示的是初始化的节点与它应当存在的下一节点之间的映射关系,在单链表表示队列的情况下, 由于新增的队列元素必然是增加在队列的尾端,即单链表的尾节点,那么element是固定为None的 """ def __init__(self, element, value): self.element = element self.value = value def __init__(self): """ 初始化三个实例,以此表示头节点、尾节点、队列元素个数 """ self._head = None self._tail = None self._size = 0 def is_empty(self): return self._size == 0 def first(self): if self.is_empty(): raise Error("the queue is empty") return self._head.value def pop(self): if self.is_empty(): raise Error("the queue is empty") value = self._head.value self._head = None return value def enqueue(self, value): new_node = self.Node(None, value) if self.is_empty(): self._head = new_node else: self._tail.element = new_node self._tail = new_node self._size += 1 def dequeue(self): if self.is_empty(): raise Error("the queue is empty") value = self._head.value if self._size == 1: self._head = None self._tail = None else: new_element = self._head.element self._head = new_element self._size -= 1 return value def __len__(self): return self._size if __name__ == "__main__": Q = LinkQueue() Q.enqueue(1) Q.enqueue(2) print(len(Q)) print(Q.first()) Q.dequeue() print(Q.first())
-
在性能方面,基于单链表实现的队列,所有操作在最坏情况下运行的时间为常数,而空间使用率和当前队列的元素个数呈现线性关系。