队列数据类型及Python实现

2023-11-15

1   队列的实现

队列是一种有次序的数据集合,其特征是,新数据项的添加总发生在一端(通常称为尾端(rear))而现存数据类型的移除总发生在另一端(通常称为首段(front))。

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

 抽象数据类型 Queue 是一个有次序的数据集合。、数据项仅添加到尾端 rear;而仅从首端 front 移除。

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

class Queue:    # 创造空队列
    def __init__(self):
        self.items = []

    def isEmpty(self):  # 判断空队列
        return self.items == []

    def enqueue(self, item):    # 将item添加队尾
        self.items.insert(0, item)

    def dequeue(self):  # 将队首删除
        return self.items.pop()

    def size(self):     # 队列中数据个数
        return len(self.items)

2   队列的应用

2.1   热土豆(击鼓传花)(约瑟夫环)

给定一个数,从 1 开始数,每数到给定数的人出局,直到仅剩一人。

用队列来实现整个问题的算法,给定参与游戏的人名列表,以及固定数字。

 模拟程序采用队列来存放所有参与游戏的人名,游戏开始,只需要让队首的人出队,随即在到队尾入队即可。

def hotPotato(namelist, num):
    simqueue = Queue()  # 初始化Queue
    [simqueue.enqueue(name) for name in namelist]
    # 将玩家名字入队
    while simqueue.size() > 1:
        # 玩家不唯一时,按照指定数字进行遍历玩家,到达指定数字时,出队。
        [simqueue.enqueue(simqueue.dequeue()) for i in range(1,num)]
        simqueue.dequeue()
    return simqueue.dequeue()

2.2   打印任务

多人共享打印机,采取 “先到先服务”的队列策略。

首要问题:

        打印系统的容量有多大。

        在能够接受的等待时间内,系统能容纳多少用户以多高频率提交打印任务。

具体实例配置如下:

        在一个实验室中,任意一小时内,大约有十名学生在场,在一小时中,每人会发起 2 次左右的打印,每次打印 1~20 页。

        打印机的性能:以草稿模式,每分钟十页。

                                  以正常模式,每分钟五页。

对问题进行抽象,确定相关对象和过程:

        对象:打印任务,打印队列,打印机

        打印任务属性:提交时间,打印页数

        打印机属性:打印速度,打印进行时间

        过程:生成和提交打印任务

                确定生成概率:每小时十位同学提交20份作业,概率 1/180 /s

                确定打印页数:实例为 1~20 ,即概率在 1~20 之间均等

                实施打印:新作业开始打印进行倒计时,到达 0 打印下一份作业

模拟流程:

        创造打印队列对象

        时间按秒为单位流逝

                按照概率生成打印作业,加入打印队列

                如果打印机空闲,且对列不为空,则取出队首任务打印,记录等待时间

                若果打印机繁忙,则按照打印速度进行 1 秒打印

                如果当前打印结束,打印机进入空闲

        时间用尽,统计平均等待时间

作业等待时间

        生成作业时间,记录生成时间戳

        开始打印时,当前时间减去生成时间

作业打印时间

        生成作业时,纪录作业的页数

        开始打印时,页数除以打印速度

import random


class Printer:  # 打印机
    def __init__(self, ppm):
        self.pagerate = ppm  # 打印速度
        self.currentTask = None  # 打印任务
        self.timeRemaining = 0  # 任务倒计时

    def tick(self):  # 打印1秒
        if self.currentTask is not None:
            self.timeRemaining = self.timeRemaining - 1
            if self.timeRemaining <= 0:
                self.currentTask = None

    def busy(self):  # 打印忙
        if self.currentTask is not 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):  # 生成时间戳
        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
        # 等待时间 currenttime - self.timestamp


def newPrintTask():
    num = random.randrange(1, 181)  # 1/180 概率生成作业
    if num == 180:
        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, 5)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

队列数据类型及Python实现 的相关文章

随机推荐

  • 栈内存与堆内存的区别

    栈内存和堆内存都是计算机中用于存储数据的内存区域 它们之间的主要区别在于 存储方式 栈内存采用 先进后出 的存储方式 而堆内存采用随机存储的方式 空间大小 栈内存的空间大小通常比堆内存的空间大小要小得多 生命周期 栈内存的生命周期比堆内存的
  • 使用Kotlin做一个简单的HTML构造器

    最近在学习Kotlin 看到了Kotlin Koans上面有一个HTML构造器的例子很有趣 今天来为大家介绍一下 最后实现的效果类似Groovy 标记模板或者Gradle脚本 就像下面 这是一个Groovy标记模板 这样的 html lan
  • Linux 下查看进程运行时长

    因为有一个Java程序运行中会持续输出大量的日志文件 可能导致磁盘空间不足 为了规避这个风险 需要根据程序运行时长估算磁盘使用量 1 查看进程的PID ps ef grep java 2 指定进程查看运行时长 PID ps o etime
  • SpringBoot优化

    一 SpringBoot全局异常处理 任何项目发生异常是不可避免的 使用全局异常捕获发生的异常是十分必要的 SpringBoot框架对全局异常捕 获提供了很好的支持 并且操作非常简单 我们只需要创建一个类和一个方法 并添加两个注解 Cont
  • LSTM分类模型

    LSTM文本分类模型 本文主要固定一个文本分类的流程 分为三个部分 数据处理 对分类文本数据集做简单的预处理 模型数据准备 处理上一步的结果 得到模型的输入样本 模型搭建和训练流程 模型使用BiLSTM 训练过程可以使用cpu或者GPU t
  • shell中的for循环的用法(C语言式)

    C语言式的for循环 用法 exp1 exp2 exp3 是三个表达式 其中exp2是判断条件 for循环根据exp2的结果来决定是否继续下一次的循环 statements是循环体语句 可以有一条 也可以有多条 do和done是shell中
  • Kotlin和Java中的IO操作

    Kotlin的特性 1 Kotlin提供了非常多 File Stream Reader Writer的拓展方法 2 使用use拓展自动关闭资源 3 小文件一次性读写操作 一 首先来看看繁琐的JavaIO操作 来读取一个文件 package
  • 有1、2、3、4四个数字,可以组成多少个互不相同且无重复的三位数?都是多少?

    这个题呢 顾名思义 就是说一个三位数的每一位都是1 2 3 4 个位十位百位上的数字不能重复 编程原理很简单 分别定义三个变量代表个位十位百位 然后使用for循环嵌套每一层循环代表一位数 如果个位十位百位都不相同 则输出 程序如下 incl
  • 微信订阅消息模板推送报错47003 data.time.value i,及解决方案

    今天又是枯燥的一天 依然敲着代码 客户有个微信消息推送的需求 找了下官方文档 微信消息推送文档 大致看了一下 需要模板ID和微信后台的小卡片参数名 随即便敲起了代码 首先定义模板类 代码如下 public class Template pr
  • 微信小程序实现一些炫酷的loading动画

    1 实现效果 2 实现原理 伪元素 css3动画 transform 3 实现代码 从上到下 从左到右依次的代码如下
  • 三款记事本替代工具 哪个最好用?

    三款记事本替代工具 哪个最好用 http www sina com cn 2008年08月27日 08 35 IT168 com Windows操作系统中自带了不少的实用小程序 但是它们大都功能简陋 有时无法满足我们的使用 此外还有一些Wi
  • MatplotLib 第二部分

    1 import numpy as np 2 import pandas as pd 3 import matplotlib pyplot as plt 4 5 导入数据 6 df pd read excel d test xlsx 7 p
  • 在VS中使用命令行参数

    在VS工具中 若要运行带有命令行参数的程序 有两种方法 方法一 在命令提示符中输入要运行的exe的文件名和要输入的参数 各参数之间用空格隔开 如exe文件为test exe 则输入 test 参数1 参数2 参数n 注意 exe文件应放在C
  • 我的软件渲染器终于初步完成了~

    记录一个大好事 在 2021年第一个月的上旬 我的软件着色器终于初具雏形了 中间参考了 很多 资料 最初是 知乎上的系列教程 https zhuanlan zhihu com p 141210744 这个教程是基于 OpenGL 右手坐标系
  • 什么是准双向口,双向口?

    C51的说明书上说 Because Ports 1 2 and 3 have fixed internal pullups they are sometimes called quasi bidirectional ports When c
  • golang 杂技

    Swap 记录一个骚操作 交换数组的两个元素 package main import fmt func main m int 1 2 Swap m 0 1 fmt Println m 2 1 func Swap i int a b int
  • C语言方波转换正弦波,方波转换成正弦波电路

    方波转换成正弦波电路 即利用RDD104可选的4各十进制CMOS除法器和一个MSFS5 开关电容滤波器来构建一个双芯片 失真率为0 2 的正弦波源 RDD104有两个引脚 可以从四个除法器divide by 10 divide by 100
  • 离线数仓经验之谈三-数仓流程规范

    数仓流程规范 目录 1 目的 2 适用范围 3 总体流程 3 1 ETL开发流程 3 1 1 需求分析 3 1 2 数据来源与数据探查 3 1 3 数据模型设计 3 1 4 ETL开发 3 1 5 测试 3 1 6 ETL上线 3 1 7
  • 想入手显示器,恳请粉丝带我推荐,必有重谢!

    坏了一个显示器 本来家里好好的两个显示器 其中1个有点雪花亮线 当时特地买的EIZO 考虑已无维修价值 打算换一个显示器 但是某宝搜了一圈 已经被各种参数和品牌搞晕掉 2K 4K 准4K IPS 60hz 144HZ 高刷 曲面屏 带鱼屏
  • 队列数据类型及Python实现

    1 队列的实现 队列是一种有次序的数据集合 其特征是 新数据项的添加总发生在一端 通常称为尾端 rear 而现存数据类型的移除总发生在另一端 通常称为首段 front 当数据项加入队列 首先出现在队尾 随着队首数据项的移除 它逐渐接近队首