1.循环队列简介:
循环队列是一种队列的实现方式,它可以避免队列空间的浪费。循环队列的特点是队列的末尾连接到队列的开头,形成一个循环。这样当队列尾部元素达到队列的最大容量时,新的元素可以循环地放入队列的开头。这种设计使得循环队列可以在一定程度上实现队列的循环利用,提高了队列的空间利用率。
2.队列及循环队列定义:
队列是一种先进先出的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头,如下图所示。
普通的顺序队列我们设置队头指针(front)和队尾指针(rear)来描述队列里的数据存储位置。初始两个指针都指向0号元素,如下图所示。
当入队时,rear指针向尾部移动,front指针则依旧指向首元素,如下图所示。
当出队时,front指针向下一个元素移动,释放出队元素,尾指针不变,入下图所示。
这就是所谓的队列“假溢出”现象,所造成得空间浪费,所以我们需要使用循环队列来解决。所谓循环队列,就是将队列的头尾相接,这样就不会出现上述问题。
但是由于rear指针相当于头指针,是不指向元素的,所以我们实际的元素数量要比队列空间少一个,如下图所示,队列总长度为6,实际元素个数为5个,还有一个被rear指针使用。
3.循环队列代码:
# 队空条件:rear = fornt
# 队满条件:(rear+1)%MaxSize == front(零位置没放元素)
# 元素进队:rear = (rear+1)%MaxSize
# 元素出队:front = (front+1)%MaxSize
MaxSize = 5
class CircleQueue: # 循环队列"""若只剩下一个空位置,该循环列表锁定,不能再加,但其优势在于可边删边加(剩两个及以上空位时),避免了假溢出"""def __init__(self):self.data = [None] * MaxSize # 初始空间self.front = 0self.rear = 0def push(self, e): # 元素e进队assert (self.rear + 1) % MaxSize != self.front # 判断队满self.rear = (self.rear + 1) % MaxSizeself.data[self.rear] = edef is_empty(self): # 判断队空return self.rear == self.frontdef pop(self): # 元素出队assert not self.is_empty() # 先判断是否为空self.front = (self.front + 1) % MaxSizereturn self.data[self.front]def gethead(self): # 获取头元素assert not self.is_empty()return self.data[(self.front + 1) % MaxSize]def getsize(self): # 获取队列长度,在front下标小于rear时,size可以直接用rear-front获取,但是如果边删边加,导致rear小于front,此方法出错return (self.rear - self.front + MaxSize) % MaxSize #该式满足上叙所有情况def dispaly(self):q=self.frontif self.front !=self.rear: #判断队空for i in range(self.getsize()):q = (q+1)%MaxSize #符合两种情况的式子print(self.data[q], end=",")else:creturn Nonedef pushk(qu, k, e):n = qu.getsize()if k < 1 or k > n + 1: #k必须正常return Falseif k <= n:for i in range(1, n + 1): #边删边进if i == k: #插个队,它插完,后面的再边删边进qu.push(e)x = qu.pop()qu.push(x)e1se: qu.push(e)return Truedef popk(qu, k):n = qu.getsize()assert 1 <= k <= nfor i in range(1, n + 1): #和上面的思想一样x = qu.pop()if i != k:qu.push(x)else:e = x # 取第k个出队的元素return eif __name__=="__main__":hh = CircleQueue()# print(hh.is_empty())# hh.push(0)# hh.push(1)# hh.push(2)# hh.push(3)# print(hh.getsize())# hh.dispaly()
# True
# 4
# 0, 1, 2, 3,
# Process
# finished
# with exit code 0
#当rear<front时# hh.push(3)# hh.push(4)# hh.push(5)# hh.push(6)# hh.pop()# hh.pop()# hh.pop()# hh.push(7)# hh.push(8)# print(hh.getsize())# hh.dispaly()
# 3
# 6,7,8,
# Process finished with exit code 0
#新增两算法调试# hh.push(2)# hh.push(3)# hh.push(4)# hh.dispaly()# hh.pushk(1,50)# print(hh.getsize())# hh.dispaly()
# 2,3,4,4
# 50,2,3,4,
# Process finished with exit code 0
# hh.push(2)
# hh.push(3)
# hh.push(4)
# hh.dispaly()
# hh.popk(1)
# print(hh.getsize())
# hh.dispaly()
# 2,3,4,2
# 3,4,
# Process finished with exit code 0