数据结构之队列(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

posted @ 2018-11-29 20:40  silence_cho  阅读(1565)  评论(0编辑  收藏  举报