保证一周更两篇吧,以此来督促自己好好的学习!代码的很多地方我都给予了详细的解释,帮助理解。好了,干就完了~加油!
声明:本python数据结构与算法是imooc上liuyubobobo老师java数据结构的python改写,并添加了一些自己的理解和新的东西,liuyubobobo老师真的是一位很棒的老师!超级喜欢他~
如有错误,还请小伙伴们不吝指出,一起学习~
No fears, No distractions.
小伙伴们中秋节快乐~
一、什么是队列
队列(Queue),顾名思义,有排队的意思,想象你要去学校食堂打饭,而打饭有着先来后到的原则,因此就需要排队,先到的人先吃-,后到的人后吃- -。这就是一个队列呀。
- 队列也是一种线性结构
- 相比数组,队列的所有操作也是数组的子集,只能从一端(队尾)添加元素,从另一端(队首)取出元素。
- 队列是一种先进先出的数据结构(先到先得)即First In First Out
- 队列相关操作:
enqueue-------入队操作
dequeue-------出队操作
getFront------看一下队首的元素是谁(对于队列,和栈是相似的,我们只对队首的元素感兴趣)
getSize-------得到队列中有效元素的个数
isEmpty-------判断队列是否为空
从用户的角度看,支持这些操作就好。具体底层实现,用户不关心。实际底层有多种实现方式。比如基于前面的数组实现,或者自己从底层再写一个队列来实现。本文基于前面所实现的数组来实现一个队列,能够自动动态扩容。当然从底层实现队列也是非常简单的,因为涉及到的操作都是我们实现的Arr类的子集。
二、实现
# -*- coding: utf-8 -*-
# Author: Annihilation7
# Data: 2018-09-24
# Python version: 3.6
import Array
class Queue:
def __init__(self, capacity=10):
"""
构造函数
:param capacity: 初始容量,默认值为10
"""
self.array = Array.Arr(capacity) # 底层由我们在第一章完成的Arr类来实现,毕竟Queue的操作只是Arr类的部分操作
def getSize(self):
"""
得到队列内有效元素的个数
时间复杂度:O(1)
:return: 有效元素的个数
"""
return self.array.getSize() # 复用Arr类的getSize方法,Arr类中已经对它的_size进行类很好的维护操作
def getCapacity(self):
"""
因为是由我们自己实现的数组作为底层数据结构,因此能够查看当前队列的容量大小,实际上这个函数用户并用不到
时间复杂度:O(1)
:return: 队列的容量
"""
return self.array.getCapacity() # 复用Arr类的getCapacity方法
def isEmpty(self):
"""
判断队列是否为空
时间复杂度:O(1)
:return: bool值,空为True
"""
return self.array.isEmpty() # 复用Arr类的isEmpty()方法
def enqueue(self, elem):
"""
入队操作,注意本文中数组右侧为队尾,左侧(索引为0的地方)为队首
时间复杂度:O(1)
:param elem: 将要入队的元素
"""
self.array.addLast(elem) # 复用Arr类的addLast操作,进行入队
def dequeue(self):
"""
出队操作,数组左边出队,就是在索引为0的地方出队。
时间复杂度:O(n)
:return: 出队的元素的值
"""
return self.array.removeFirst()
def getFront(self):
"""
拿到对首的元素,因为往往队首的元素是我们关心的元素。
时间复杂度:O(1)
:return: 队首元素
"""
return self.array.getFirst() # 复用Arr类的getFirst操作,也不用进行判空神马的类,因为Arr类中的函数都帮我们干了
def printQueue(self):
"""打印队列的操作"""
print('Queue: Front--- ', end='') # 左边是队首
for i in range(self.getSize()):
if i != self.getSize() - 1: # 强迫症。。为了打印美观- -
print(self.array[i], end=' ') # 别忘了我们的Arr是支持索引操作的哦
else:
print(self.array[i], end='')
print(' ---Tail') # 右边是队尾哦
print('Size: %d' % (self.getSize())) # 有效元素个数的打印
三、测试
import queue # 我们的Queue类写在这个py文件中了
import numpy as np
np.random.seed(7)
test = queue.Queue()
print(test.getSize())
print(test.getCapacity())
print(test.isEmpty())
for i in range(17):
test.enqueue(np.random.randint(10))
test.printQueue()
for i in range(7):
test.dequeue() # 不需要dequeue的返回值了
test.printQueue()
print(test.getFront())
四、输出
0
10
True
Queue: Front--- 4 9 6 3 3 7 7 9 7 8 9 8 7 6 4 0 7 ---Tail
Size: 17
Queue: Front--- 9 7 8 9 8 7 6 4 0 7 ---Tail
Size: 10
9
五、一个小问题
既然队列的出队操作是O(n)的时间复杂度,那么有没有什么办法让入队和出队都变成O(1)的时间复杂度呢?答案就在我下一节要讲的循环队列中!干就完了,下章见!
若有还可以改进、优化的地方,还请小伙伴们批评指正!