【数据结构与算法学习笔记-Queue】

本文为学习笔记,感兴趣的读者可在MOOC中搜索《数据结构与算法Python版》或阅读《数据结构(C语言版)》(严蔚敏)
目录链接:https://blog.csdn.net/floating_heart/article/details/123991211

1.2.1 队列抽象数据类型及实现

队列是一种有次序的数据集合,其特征是:

  • 新数据项的添加总发生在一端(通常称为“尾rear”端)

  • 现存数据项的移除总发生在另一端(通常称为“首front”端)

当数据项加入队列,首先出现在队尾,随着队首数据项的移除,它逐渐接近队首。

这种次序安排的原则称为(FIFO:First-in first-out)先进先出

“队列”定义的操作:

**Queue():**创建一个空队列对象,返回值为Queue对象;
**enqueue(item):**将数据项item添加到队尾,无返回值;
**dequeue():**从队首移除数据项,返回值为队首数据项,队列被修改;
**isEmpty():**测试是否空队列,返回值为布尔值
**size():**返回队列中数据项的个数。

实现

代码:Python

class Queue:
  def __init__(self):
      self.item = []

  def isEmpty(self):
    return self.items == []

  def enqueue(self,item):
    self.item.insert(0,item)

  def dequeue(self):
    return self.item.pop()
  
  def size(self):
    return len(self.item)

代码:JavaScript-prototype

function Queue() {
  this.item = []
}
Queue.prototype.isEmpty = function () {
  return this.item.length == 0
}
Queue.prototype.enqueue = function (item) {
  this.item.unshift(item)
}
Queue.prototype.dequeue = function () {
  return this.item.pop()
}
Queue.prototype.size = function () {
  return this.item.length
}
module.exports = { Queue }

代码:JavaScript-class

export default class Queue {
  constructor() {
    this.item = []
  }
  isEmpty() {
    return this.item.length == 0
  }
  enqueue(item) {
    this.item.unshift(item)
  }
  dequeue() {
    return this.item.pop()
  }
  size() {
    return this.item.length
  }
}

1.2.2 热土豆问题(约瑟夫问题)

问题描述:

传说犹太人反叛罗马人,落到困境,约瑟夫和39人决定殉难,坐成一圈儿,报数1~7,报到7的人由旁边杀死

算法说明:

游戏时,队首始终是持有土豆的人

传递了num次后,将队首的人移除,不再入队如此反复,直到队列中剩余1人

实现:

代码:Python

from Queue import Queue

def hotPotato(namelist,num):
  simqueue = Queue()
  for name in namelist:
    simqueue.enqueue(name)
  
  while simqueue.size()>1:
    for i in range(num):
      simqueue.enqueue(simqueue.dequeue())
    simqueue.dequeue()
  
  return simqueue.dequeue()

代码:JavaScript

import Queue from './Queue_c.js'
// const { Queue } = require('./Queue.js')

function hotPotato(namelist, num) {
  let simqueue = new Queue()

  for (let name of namelist) {
    simqueue.enqueue(name)
  }

  while (simqueue.size() > 1) {
    for (let i = 0; i < num; i++) {
      simqueue.enqueue(simqueue.dequeue())
    }
    simqueue.dequeue()
  }

  return simqueue.dequeue()
}

1.2.3 打印任务

问题描述:

决策支持问题但无法通过规则直接计算:
多人共享一台打印机,采取“现到先服务”的队列策略来执行打印任务

一个具体的实例配置如下:
一个实验室,在任意的一个小时内,大约有10名学生在场,这一小时中,每人会发起2次左右的打印,每次1~20页

打印机的性能是:
以草稿模式打印的话,每分钟10页,以正常模式打印的话,打印质量好,但速度下降为每分钟5页。

问题是:
怎么设定打印机的模式,让大家都不会等太久的前提下尽量提高打印质量?

算法说明:

抽象问题,以时间为单位进行任务

对象:
**打印任务:**提交时间、打印页数
**打印队列:**具有FIFO性质的打印任务队列
**打印机:**打印速度、是否忙

过程:生成和提交打印任务
生成概率:每秒1/180
打印页数:1~20页

过程:实施打印
当前的打印作业:正在打印的作业
打印结束倒计时:新作业开始打印时开始倒计时,回0表示打印完毕,可以处理下一个作业

模拟时间:
统一的时间框架:以最小单位(秒)均匀流逝的时间,设定结束时间
同步所有过程:在一个时间单位里,对生成打印任务和实施打印两个过程各处理一次

模拟流程:
1.创建打印队列对象
2.时间按照秒的单位流逝

按照概率生成打印作业,加入打印队列;
如果打印机空闲,且队列不空,则取出队首作业打印,记录此作业等待时间;
如果打印机忙,则按照打印速度进行1秒打印;
如果当前作业打印完成,则打印机进入空闲

3.时间用尽,开始统计平均等待时间

获取作业等待时间:
生成作业时,记录生成的时间戳
开始打印时,当前时间减去生成时间即可

获取作业的打印时间:
生成作业时,记录作业的页数
开始打印时,页数除以打印速度即可

实现:

代码:Python

from Queue import Queue

import random
# 打印机对象
class Printer:
  def __init__(self,ppm) -> None:
      self.pagerate = 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 startNext(self,newtask): #添加新任务 初始化时间
    self.currentTask = newtask
    self.timeRemaining = newtask.getPages() * 60 / self.pagerate
#任务对象 记录生成时间和页数
class Task: 
  def __init__(self,time) -> None:
      self.timestamp = time
      self.pages = random.randrange(1,21)
  
  def getStamp(self):
    return self.timestamp

  def getPages(self):
    return self.pages

  def waitTime(self,currenttime):
    return currenttime - self.timestamp
  
def newPrintTask():
  num = random.randrange(1,181)
  if num == 1:
    return True
  else:
    return False

def simulation(numSeconds,pagesPerMinute):

  labprinter = Printer(pagesPerMinute)
  printQueue = Queue() #打印队列对象
  waitingtimes = []

  for currentSecond in range(numSeconds):
    if newPrintTask():#判断是否有新任务生成,加入队列中
      task = Task(currentSecond)
      printQueue.enqueue(task)
    if (not labprinter.busy()) and (not printQueue.isEmpty()):#打印机空闲且有任务存在
      nexttask = printQueue.dequeue()
      waitingtimes.append(nexttask.waitTime(currentSecond))
      labprinter.startNext(nexttask)
    labprinter.tick()

  averageWait = sum(waitingtimes) / len(waitingtimes)
  print("Average Wait %6.2f secs %3d tasks remaining."%(averageWait,printQueue.size()))

for i in range(10):
  simulation(3600,10)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值