数据结构之队列(Queue)
1,队列的定义
队列:是一种先进先出的数据结构,如下图所示,现进去的数据在队列前面(front),先出队列,后进入队列的数据在后面(rear),后出队列。
队列常用操作:
q=Queue() #创建队列 q.enqueue(item) # 数据入队列,在队列后面 q.dequeue() #数据出队列,从队列前面移出数据并返回 q.isEmpty() #返回队列是否为空 q.size() #返回队列大小
操作示例:
2,用python实现队列
可以用python的list来实现队列,其定义如下面代码所示。 (其中enqueue和dequeue也可以用append和pop(0)来实现)
class Queue(object): def __init__(self): self.items = [] def enqueue(self,item): self.items.insert(0,item) def dequeue(self): return self.items.pop() def isEmpty(self): return self.items==[] def size(self): return len(self.items)
3,队列的应用
3.1 约瑟夫环问题(Josephus problem):n个人围成一圈,从1开始报数,每当有人报到m时,他被淘汰,下一个人继续从1开始报数,问最后的获胜者是谁?
Hot potato game:N个人编号1~N,围坐成一个圆圈。从1号人开始传递一个热土豆,经过M次传递后拿着热土豆的人被清除离座,由坐在后面的人拿起热土豆继续进行游戏。最后剩下的人获胜.
上面两个问题相同,如果M=0和N=5,则游戏人依序被清除,5号游戏人获胜。如果M=1 和N=5,那么被清除的人的顺序是2,4,1,5,最后3号人获胜。
代码实现如下(n=5,m=7):
#n个人围成一圈,第一个人从1开始报数,每当有人报到m时,他被淘汰,下一个人继续从1开始报数
def josephus(people_list,num): q = Queue() for people in people_list: q.enqueue(people) while q.size()>1: for i in range(num-1): q.enqueue(q.dequeue()) q.dequeue() return q.dequeue() people_list = [1,2,3,4,5] print josephus(people_list,7)
(上述代码中people_list = [1,2,3,4,5],加入Queue中后q=[5,4,3,2,1],people_list的正序报数对应q中的倒序报数)
3.2. 模拟打印机任务队列
有这样一种情景:有一台打印机,其打印速度可以调节,每分钟打印5页,10页或15页,打印速度越快质量越差。平均每三分钟会有一个学生来打印,打印内容在20页以内,打印机的速度该设置为多少时,才能保证打印质量,同时减少学生的等待时间?
模拟代码如下:
#模拟打印机任务队列 import random class Printer(object): def __init__(self,ppm): self.printrate = ppm # ppm 每分钟打印多少页 self.currentTask = None self.timeRemaining=0 def tick(self): if self.currentTask!=None: self.timeRemaining = self.timeRemaining-1 if self.timeRemaining<=0: self.currentTask=None def busy(self): if self.currentTask!=None: return True else: return False def startTask(self, newTask): self.currentTask=newTask self.timeRemaining = newTask.getPages()*60/self.printrate class Task(object): def __init__(self,time): self.timestamp = time self.pages = random.randrange(1,21) def getPages(self): return self.pages def getStamp(self): return self.timestamp def waitTime(self,currentTime): return currentTime-self.timestamp def simulation(numSeconds,pagesPerMinute): printer = Printer(pagesPerMinute) printqueue = Queue() waitingtime = [] for currentSecond in range(numSeconds): if printTask(): task = Task(currentSecond) printqueue.enqueue(task) if (not printer.busy()) and (not printqueue.isEmpty()): newTask = printqueue.dequeue() waitingtime.append(newTask.waitTime(currentSecond)) printer.startTask(newTask) printer.tick() averageWait = sum(waitingtime)/len(waitingtime) print "Average wait %6.2f seconds, %d tasks remaining"%(averageWait,printqueue.size()) #平均每三分钟有一个打印任务 def printTask(): num = random.randrange(1,181) if num==180: return True else: return False for i in range(10): simulation(3600,10) # 模拟时间60分钟,打印机速度为10
打印机速度为10,60分钟内模拟结果如下:(平均等待时间158-947秒,剩余2-10个打印任务)
参考:http://interactivepython.org/runestone/static/pythonds/BasicDS/WhatIsaQueue.html