队列的概念
队列是由一系列对象组成的集合,这些对象的插入和操作和删除遵循先进先出(First in First out ,FIFO),也就是说只有处于队列最前面的元素才能被删除;
常见概念:
- 队尾:将队列中允许插入的一端称为队尾,一般指向当前的元素所在的位置;
- 对首:将队列中允许删除的一端称为对首,队尾一般指向下一个数据储存的位置;
队列数据结构图解:
因为入队和出队操作分别再队尾和队首进行,所以增加front来指示队首的元素的位置,rear来指示队尾元素的下一个存储单元的位置。
按照实现方法(基于那个数据结构)队列分类:
- 顺序队列,即基于数组实现
- 链表队列,即基于链表实现
循环队列
上述队列,顺序队列和链表队列中,如果不断重复地往队列中添加元素,然后删除队首的元素,随着时间的推移,就会发生这样的事,底层的大小将逐渐增长到O(m),(假设底层的数组是无限大的),如下图所示。其中m是等于自队列创建以来进行追加元素操作的数量总和,而不是当前队列中元素的数量,故系统可能让这些元素存储在一个任意大小的列表中,为了使队列更加健壮,实现循环队列来解决这种问题,
循环队列原理:
让队列的前端趋于右端,并且让队列内的元素在底层数组的尾部“循环”,即假定底层数组的长度为固定值N,它比实际队列的中的元素的数量大。
如下图所示,在经过一系列的插入元素,删除元素后,在队列尾部重新插入元素时,如果超过底层数组的大小,会将数据插入到底层数组的头部;
实现:
主要用到取模操作来实现队列的队尾和队首索引位置的更新,F= (f+1)%N,N为数组的大小,f为当前索引,F为更新后的索引。
例如:
顺序队列
# -*- coding: utf-8 -*-
"""
Created on Thu Dec 19 09:53:44 2019
@author: dell
"""
#队列的抽象数据描述:先进先出
#队列的删除只能在表的尾部进行
#删除操作只能在表头进行
#在队列中允许进行插入的一端称为队尾,
#允许删除的操作的一端称为队首
#队列的插入操作叫入队
#队列的删除操作叫做出队
"""顺序对列"""
#对列的操作在对首和队尾进行,所以增加变量front来指示对首的位置,rear指示队尾元素的下一个‘
#储存单元的位置
"""顺序对列"""
#对列的操作在对首和队尾进行,所以增加变量front来指示对首的位置,rear指示队尾元素的下一个‘
#储存单元的位置
class SqQueue():
def __init__(self,maxsize):
self.maxsize = maxsize
self.quequeElem = [None] * self.maxsize
self.front = 0 #指向对首的元素
self.rear = 0 #指向队尾元素的下一个存储单元
def clear(self):
self.front = 0
self.rear = 0
def isEmpty(self):
return self.front == self.rear
def length(self):
return self.rear - self.front
def peek(self):
#返回对首元素
if self.isEmpty():
return None
else:
return self.quequeElem[self.front]
def offer(self,x):
#将数据元素x插入对列成为队尾的元素
if self.rear == self.maxsize:
raise Exception("对列已满")
else:
self.quequeElem[self.rear] = x
self.rear += 1
def poll(self):
#将对首的元素删除,并返回其值
if self.isEmpty():
return None
p = self.quequeElem[self.front]
self.front += 1
return p
def display(self):
for i in range(self.front,self.rear):
print(self.quequeElem[i],end=' ')
squeue = SqQueue(5)#设置队列的大小为5
squeue.offer(5)
squeue.offer(7)
squeue.offer(8)
print("队列的元素:")
squeue.display()
print("打印队首元素")#队首元素应该为5,先进先出
squeue.peek()#
print("队列的元素:")
squeue.display()
队列的元素:
5 7 8
print("打印队首元素")
squeue.peek()
打印队首元素
Out[36]: 5
链表队列--有点问题
"""
链表对列
"""
class Node(object):
def __init__(self,data=None,next=None):
self.data = data#数据保存位置
self.next = next#指向下一个数据位置
class LinkQueue():
def __init__(self):
self.front = None
self.rear = None
def clear(self):
self.front = 0
self.rear = 0
def isEmpty(self):
return self.front is None
def length(self):
p = self.front
i = 0
while p is not None:
p = p.next
i += 1
return i
def peek(self):
if self.isEmpty():
return None
else:
return self.front.data
def offer(self,x):
#将数据元素x插入对列成为队尾的元素
s = Node(x)#创建新的节点
if not self.isEmpty():
self.rear.data = s
else:
self.front = s
self.rear = s
def poll(self):
#将对首的元素删除,并返回其值
if self.isEmpty():
return None
p = self.front
self.front = self.front.next
if p == self.rear:
self.rear = None
def display(self):
#打印队列的数据
p = self.front
while p is not None:
print(p.data,end='')
p = p.next
squ = LinkQueue()
#添加元素
squ.offer(5)
squ.offer(7)
squ.offer(8)
print("队列的元素:")
squ.display()
print("打印队首元素")#队首元素应该为5,先进先出
squ.peek()#
循环队列
"""
循环对列:
对列最多放的元素:maxsize -1
队空的条件:
front = rear
对满的条件:
front = (rear + 1) % maxsize
"""
class CircleQueue():
def __init__(self,maxsize):
self.maxsize = maxsize
self.quequeElem = [None] * self.maxsize
self.front = 0
self.rear = 0
def clear(self):
self.front = 0
self.rear = 0
def isEmpty(self):
return self.front == self.rear
def length(self):
return (self.rear - self.front +self.maxsize) % self.maxsize
def peek(self):
if self.isEmpty():
raise Exception("对列是空的")
else:
return self.quequeElem[self.front]
def offer(self,x):
if (self.rear + 1) % self.maxsize == self.front:
raise Exception("对列已满")
self.quequeElem[self.rear] = x
self.rear = (self.rear + 1) % self.maxsize
def poll(self):
if self.isEmpty():
return None
p = self.quequeElem[self.front]
self.front = (self.front + 1) % self.maxsize
return p
def display(self):
i = self.front
while i != self.rear:
print(self.quequeElem[i],end=' ')
i = (i + 1) % self.maxsize
circleQueue = CircleQueue(5)#设置队列的大小为5
circleQueue.offer(8)
circleQueue.offer(7)
circleQueue.offer(6)
circleQueue.offer(5)
circleQueue.poll()
circleQueue.display()
circleQueue = CircleQueue(5)
circleQueue.offer(8)
circleQueue.offer(7)
circleQueue.offer(6)
circleQueue.offer(5)
circleQueue.poll()
Out[13]: 8
circleQueue.display()
7 6 5