线性结构:队列

news2024/12/26 21:18:45

文章目录

      • 队列定义
      • 队列应用
        • 热土豆问题
        • 打印任务

队列定义

队尾进,队头出

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

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

image-20230720094342884

新加入的数据项必须在数据集末尾等待,而等待时间最长的数据项则是队首

这种次序安排的原则称为( FIFO:First-infirst-out)先进先出或“先到先服务first-come first-served”

  • 队列的例子出现在我们日常生活的方方面面:排队队列仅有一个入口和一个出口
  • 不允许数据项直接插入队中,也不允许从中间移除数据项

队列应用

  • 打印队列:有任务在打印时,后来的打印请求排成队列FIFO

  • 进程调度:原则综合了“先来先服务”

  • 键盘缓冲:键盘敲击并不马上显示在屏幕上,而是将尚未敲击的字符暂存在队列性质缓冲区

队列操作定义

  • Queue():创建一个空队列对象,返回值为Queue对象;
  • enqueue(item):将数据项item添加到队尾,无返回值;
  • dequeue():从队首移除数据项,返回值为队首数据项,队列被修改;
  • isEmpty():测试是否空队列,返回值为布尔值
  • size():返回队列中数据项的个数
image-20230720095628088
class Queue:
    def __init__(self):  # 默认列表最左边为队尾,最右边为队首
        self.items = []  # 容纳Queue数据项

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

    def size(self):
        return len(self.items)

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

    def dequeue(self):  # O(1)
        return self.items.pop()  # 弹出队首数据项并返回值

队列应用

热土豆问题

类似击鼓传花

用队列来实现热土豆问题的算法,参加游戏的人名列表,以及传土豆次数num,算法返回最后剩下的人名

image-20230720103911474

模拟算法

模拟程序采用队列来存放所有参加游戏的人名,按照传递土豆方向从队首排到队尾

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

模拟游戏开始,只需要将队首的人出队,随即再到队尾入队,算是土豆的一次

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fp3d0EfO-1689843594037)(./image/image-20230720104036165.png)]

from queue import Queue

def hot_potato(name_list, num):
    simqueue = Queue()  # 创建一个空队列
    for name in name_list:  # 名字全部入列
        simqueue.enqueue(name)
    for i in range(num):  # 进行一轮土豆传递
        # 土豆默认在队首
        simqueue.enqueue(simqueue.dequeue())  # 队首出列重新进队尾
    while simqueue.size() > 1:  # 一轮结束,队首持续出列,直至只剩一人为土豆持有者
        simqueue.dequeue()
    return simqueue.dequeue()

print(hot_potato(["bill", "hary", "gege", "hzh"], 7))
# gege

打印任务

多人共享打印机采取“先来先服务”的队列策略来执行打印任务

实例配置:

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

打印机的性能是:

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

问题建模

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

  • 打印任务的属性:提交时间、打印页数
  • 打印队列的属性:具有FIFO性质的打印任务队列
  • 打印机的属性:打印速度、是否忙
image-20230720110257378

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

  • 确定生成概率:实例为每小时会有10个学生提交的20个作业,这样,概率是每180秒会有1个作业生成并提交,概率为每秒1/180
  • 确定打印页数:实例是120页,那么就是120页之间概率相同。
image-20230720112504781

过程:实施打印

  • 当前的打印作业:正在打印的作业

  • 打印结束倒计时:新作业开始打印时开始倒计时,回0表示打印完毕,可以处理下一个作业

模拟时间:

  • 统一的时间框架:以最小单位(秒)均匀流逝的时间,设定结束时间

  • 同步所有过程:在一个时间单位里,对生成打印任务实施打印两个过程各处理一次

模拟流程:

  1. 创建打印队列对象

  2. 时间按照秒的单位流逝

    • 按照概率生成打印作业,加入打印队列,如果打印机空闲,且队列不空,则取出队首作业打印,记录此作业等待时间如果打印机忙,则按照打印速度进行1秒打印。如果当前作业打印完成,则打印机进入空闲
  3. 时间用尽,开始统计平均等待时间

  4. 作业的等待时间

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

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

  5. 作业的打印时间

    • 生成作业时,记录作业的页数

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

打印机模拟代码

创建打印机类

from queue import Queue
import random
# 打印机类
class Printer:
    def __init__(self, ppm):
        self.pagerate = ppm  # ppm:打印速度每分钟几张
        self.current_task = None  # 当前打印任务
        self.time_remaining = 0  # 任务倒计时

    def tick(self):  # 打印一秒
        if self.current_task != None:
            self.time_remaining = self.time_remaining - 1
            if self.time_remaining <= 0:
                self.current_task = None

    def busy(self):  # 打印机是否忙
        if self.current_task != None:
            return True
        else:
            return False

    def start_next(self, new_task):  # 打印新作业
        self.current_task = new_task  # 将新任务设置为当前任务
        self.time_remaining = new_task.get_pages() * 60 / self.pagerate  # 任务所需时间:页数*60s/打印速度

创建任务类

# 任务类
class Task:
    def __init__(self, time):
        self.timestamp = time  # 生成时间戳
        self.pages = random.randrange(1, 21)  # 随机生成打印页数

    def get_stamp(self):
        return self.timestamp

    def get_pages(self):
        return self.pages

    def wait_time(self, currenttime):
        return currenttime - self.timestamp  # 当前时间-时间戳=等待时间

新打印任务

# 新打印任务
def new_print_task():
    num = random.randrange(1, 181)  # 1/180的概率生成作业
    if num == 180:
        return True
    else:
        return False

主函数:模拟打印任务

# 模拟
def simulation(num_seconds, pages_perminute):  # 模拟时间,打印机模式(速度)
    labprinter = Printer(pages_perminute)  # 打印机对象
    print_queue = Queue()  # 打印队列
    waiting_times = []  # 记录等待时间列表
# 模拟时间流逝
    for current_second in range(num_seconds):
        if new_print_task():  # 生成新作业
            task = Task(current_second)  # 生成一个任务对象
            print_queue.enqueue(task)  # 将任务入打印队尾
        # 打印机空闲且打印队列有作业时,打印队列队首出队,变为新打印任务
        if (not labprinter.busy()) and (not print_queue.is_empty()):
            next_task = print_queue.dequeue()
            waiting_times.append(next_task.wait_time(current_second))  # 将任务等待时间记录到列表
            labprinter.start_next(next_task)  # 打印机开始新任务

        labprinter.tick()  # 打印机打印一秒
# 打印平均等待时间
    average_wait = sum(waiting_times) / len(waiting_times)
    print("平均等待时间:%6.2f秒 任务剩余:%3d" % (average_wait, print_queue.size()))

测试结果:

按照每分钟打印5张速度,运行3600s(1小时),模拟运行3次

for i in range(10):
    simulation(3600, 5)
# 平均等待时间:108.89秒 任务剩余:  0
# 平均等待时间: 44.33秒 任务剩余:  0
# 平均等待时间: 74.18秒 任务剩余:  0
# 平均等待时间: 77.48秒 任务剩余:  1
# 平均等待时间:167.89秒 任务剩余:  0
# 平均等待时间:170.67秒 任务剩余:  0
# 平均等待时间:137.10秒 任务剩余:  0
# 平均等待时间: 96.61秒 任务剩余:  3
# 平均等待时间:285.11秒 任务剩余:  0
# 平均等待时间:250.09秒 任务剩余:  1

ps:如果将打印机速度改成10张每分钟,等待时间会大大减少,任务也都无剩余,但是牺牲了打印质量

for i in range(10):
    simulation(3600, 10)
# 平均等待时间: 24.18秒 任务剩余:  0
# 平均等待时间: 22.43秒 任务剩余:  0
# 平均等待时间:  6.05秒 任务剩余:  0
# 平均等待时间: 25.00秒 任务剩余:  0
# 平均等待时间: 25.71秒 任务剩余:  0
# 平均等待时间: 30.17秒 任务剩余:  0
# 平均等待时间:  9.41秒 任务剩余:  0
# 平均等待时间:  5.56秒 任务剩余:  0
# 平均等待时间:  7.86秒 任务剩余:  0

加粗样式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/777407.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

刷题记录-2最短路径

考点&#xff1a; 图论-最短路-Dijkstra 解题&#xff1a; c #include <iostream> #include <vector> #include <queue> using namespace std; const long long inf 0x3f3f3f3f3f3f3f3fLL; const int num 3e52; struct edge {int from,to;long long w;e…

算法竞赛入门【码蹄集新手村600题】(MT1001-1020)

算法竞赛入门【码蹄集新手村600题】(MT1001-1020&#xff09; 目录MT1001 程序设计入门MT1002 输入和输出整型数据MT1003 整数运算MT1004 求余MT1005 输入和输出实型数据MT1006 实型数运算MT1007 平均分MT1008 圆球等的相关运算MT1009 公式计算MT1010 输入和输出字符型数据MT10…

【Visual Studio】Qt 在其他 cpp 文件中调用操作 ui 界面控件

知识不是单独的&#xff0c;一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏&#xff1a;Visual Studio。 还整了一个如何相互之间调用函数的文章&#xff0c;感兴趣可以看&#xff1a;【Visual Studio】Qt 在其他 cpp 文件中调用主工程下文件中的函数。 文章目录 …

第四章:包围体

第四章&#xff1a;包围体 引言-包围体&#xff08;1&#xff09;包围体测试和几何体测试&#xff08;2&#xff09;包围体测试的代价和作用&#xff08;3&#xff09;相交测试的优化&#xff08;4&#xff09;包围体相关章节和主旨 一、BV 期望特征1.1 有效的包围体1.2 包围体…

docker 网络配置详解

目录 1、docker网络模式 2、容器和容器之间是如何互通 3、容器之间互通 --link 3、自定义网络 4、不通网段的容器进行网络互通 1、docker网络模式 docker 网络模式采用的是桥接模式&#xff0c;当我们创建了一个容器后docker网络就会帮我们创建一个虚拟网卡&#xff0c;这…

Electron 学习_在进程之间通信

1.问题&#xff1a;Electron的主进程和渲染进程有着清楚的分工&#xff0c;并且不可互换。从渲染进程直接访问Node.js 接口&#xff0c;亦或者 从主进程访问HTML文档对象模型(DOM)都是不可能的 2.解决方法&#xff1a;使用进程间通信 (IPC) 可以使用 Electron 的ipcMain 模块和…

Redisson限流器RRateLimiter使用及源码分析

一、使用 使用很简单、如下 // 1、 声明一个限流器 RRateLimiter rateLimiter redissonClient.getRateLimiter(key);// 2、 设置速率&#xff0c;5秒中产生3个令牌 rateLimiter.trySetRate(RateType.OVERALL, 3, 5, RateIntervalUnit.SECONDS);// 3、试图获取一个令牌&#…

TCP首部格式【TCP原理(笔记五)】

文章目录 TCP首部格式源端口号&#xff08;Source Port&#xff09;目标端口号&#xff08;Destination Port&#xff09;序列号&#xff08;Sequence Number&#xff09;确认应答号&#xff08;Acknowledgement Number&#xff09;数据偏移&#xff08;Data Offset&#xff09…

Oracle 普通视图 (Oracle Standard Views)

视图&#xff08;views&#xff09;是一种基于表的"逻辑抽象"对象&#xff0c;由于它是从表衍生出来的&#xff0c;因此和表有许多相同点&#xff0c;我们可以和对待表一样对其进行查询/更新操作。但视图本身并不存储数据&#xff0c;也不分配存储空间。 本文只讨论普…

Linux下搭建pyqt5开发环境—基于Pycharm

防踩坑Tips&#xff1a; 1、不能学windows那样直接用pip安装PyQt5Designer和pyqt5-tools。这两个模块最根本的是用的windows的程序&#xff0c;linux上是运行不了的&#xff0c;特别是PyQt5Designer&#xff0c;会提示安装失败。 2、推荐在python环境安装同系统版本一致的pyq…

2023.7.16 第五十九次周报

目录 前言 文献阅读:跨多个时空尺度进行预测的时空 LSTM 模型 背景 本文思路 本文解决的问题 方法论 SPATIAL 自动机器学习模型 数据处理 模型性能 代码 用Python编写的LSTM多变量预测模型 总结 前言 This week, I studied an article that uses LSTM to solve p…

数据分析系统中的六边形战士——奥威BI系统

数据分析软件可以对收集的数据进行分析和报告&#xff0c;帮助企业获得更深入的数据洞察力&#xff0c;从而推动企业数字化运营决策&#xff0c;提高决策效率与质量。进入大数据时代&#xff0c;企业对数据分析软件的要求也在水涨船高&#xff0c;传统的数据分析软件显然已不能…

数据结构 单向链表(不循环)的基础知识和基础操作

头定义&#xff1a; typedef int datatype; typedef struct Node {//数据域存储数据datatype data;//指针域存储下一个地址struct Node *next; }*Linkelist; 创建节点 Linkelist create_node()//创建新节点 {Linkelist node(Linkelist)malloc(sizeof(struct Node));if(nodeN…

Elasticsearch 源码探究 001——故障探测和恢复机制

1、Elasticsearch 故障探测及熔断背景 探究Elasticsearch7.10.2 节点之间的故障探测以及熔断故障是怎么做的&#xff0c;思考生产上的最佳实践。 服务端故障场景&#xff1a; 单个master挂掉 除了断点断网&#xff0c;状态同步异常&#xff0c;主master也会认为自己已经失败&am…

ASPICE V模型之软件需求

ASPICE V模型之软件需求 了解ASPICE认识软件需求软件需求分解软件需求工作流程 了解ASPICE ASPICE全称是“Automotive Software Process Improvement and Capacity Determination”汽车软件过程改进及能力评定&#xff0c;是汽车行业用于评价软件开发团队的研发能力水平的模型框…

全球生成式AI大竞赛,Llama 2大模型现已可在亚马逊云科技上使用

一直以来Llama可以说是AI社区内最强大的开源大模型。但因为开源协议问题&#xff0c;一直不可免费商用。7月19日&#xff0c;Meta发布了大家期待已久的免费可商用版本Llama 2。一夜之间&#xff0c;大模型格局再次发生巨变。 作为Meta宣布的首批合作伙伴之一&#xff0c;现亚…

Ubuntu 安装Postgresql与PostGIS

1.前言 最近在做GIS分析&#xff0c;采集设备的经纬度点判断是否进出围栏以及是否产生道路偏移报警&#xff0c;在之前的文章有介绍过Windows下使用C#来实现&#xff0c;参考文章&#xff1a;利用PostgresqlPostgis进行空间地理信息分析&#xff08;道路偏移&#xff0c;进出电…

sql注入---报错注入

updatexml&#xff08;&#xff09;&#xff1a;对XML文档数据进行查询和修改 extractvalue&#xff08;&#xff09;&#xff1a;对XML文档数据进行查询 floor&#xff08;&#xff09;&#xff1a;取整的函数 前提是未关闭数据库报错函数&#xff0c;对于一些SQL语句的错误…

Java反射、动态代理

文章目录 反射什么是动态代理&#xff1f;程序为什么需要代理?代理长什么样? 反射 java反射机制原理&#xff1a;我们写的源代码是.java文件&#xff0c;通过javac编译后成为.class文件&#xff0c;即字节码文件&#xff0c;程序执行时&#xff0c;JVM会类加载字节码文件到内…

浅谈单片机

目录 1.什么是单片机 2.单片机的作用&#xff1f; 3.单片机的种类 4.如何学好单片机 5. 单片机的就业前景 1.什么是单片机 单片机&#xff08;Microcontroller Unit&#xff0c;简称MCU&#xff09;是一种集成了微处理器核心、存储器、输入输出端口和各种外围功能模块于一体…