Python数据结构与算法篇(三)-- 队列的实现和应用

news2024/9/21 20:48:38

1 队列

1.1 简单队列

        队列是一种有次序的数据集合,其特征是新数据项的添加总发生在一端(通常称为“尾rear”端);而现存数据项的移除总发生在另一端(通常称为“首front”端)。当一个元素被加入到队列之后,它就从队尾开始向队首前进,直到它成为下一个即将被移出队列的元素。

        最新被加入的元素必须处于队尾,在队列停留最长时间的元素处于队首。这种原则有时候叫做“先进先出”(FIFO, first-in first-out),有时候也叫做“先到先服务”。

1.2 双端队列

        双端队列(deque 或 double-ended queue)与队列类似,也是一系列元素的有序组合。其两端称为队首(front)和队尾(rear),元素在到达两端之前始终位于双端队列中。与队列不同的是,双端队列对元素添加和删除的限制不那么严格,元素可以从两端插入,也可以从两端删除。可以说,双端队列这种混合的线性数据结构拥有栈和队列各自拥有的所有功能。图3是一个由Python数据对象构成的双端队列。 应当指出,双端队列虽然具备栈和队列的许多特征,但其中的数据项不满足严格的“后进先出”或“先进先出”顺序,这使得插入和删除操作的规律性需要由用户自己维持。

图3 一个由 Python 数据对象构成的双端队列

2 队列的抽象数据类型

2.1 简单队列

        抽象数据类型队列通过以下的一些结构和操作来定义。如前文所述,一个队列由一系列有序的元素构成,它们从叫做“队尾”的一端进入队列,再从叫做“队首”的另一端被移出队列。队列保持“先进先出”的特性。下面是队列的一些操作:

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

        我们需要决定列表的哪一端做队尾,哪一端用来做队首。下面的一段代码设定队列的队尾在列表的0位置。这使得我们能够利用列表的insert 功能来向队列的队尾添加新的元素。而pop操作则可以用来移除队首的元素(也就是列表的最后一个元素)。这也意味着enqueue的复杂度是O(n),而dequeue的复杂度是O(1)。

class Queue:
    def __init__(self):
        self.items = []
    
    def is_empty(self):
        return self.items == []
    
    def enqueue(self, item):        # 复杂度O(n)
        self.items.insert(0, item)
    
    def dequeue(self):      # 复杂度O(1)
        return self.items.pop()

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

2.2 双端队列

        双端队列的定义的操作如下:

Deque():创建一个空双端队列
addFront(item):将item加入队首
addRear(item):将item加入队尾
removeFront():从队首移除数据项,返回值为移除的数据项
removeRear():从队尾移除数据项,返回值为移除的数据项
isEmpty():返回deque是否为空
size():返回deque中包含数据项的个数
class Deque:
    def __init__(self):
        self.items = []

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

    def addFront(self, item):
        self.items.append(item)

    def addRear(self, item):
        self.items.insert(0,item)

    def removeFront(self):
        return self.items.pop()

    def removeRear(self):
        return self.items.pop(0)

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

3 队列的应用

3.1 热土豆问题

        首先,让我们来考虑一个叫做热土豆的儿童游戏。在这个游戏中(见图1)小孩子们围成一个圆圈并以最快的速度接连传递物品,并在游戏的一个特定时刻停止传递,这时手中拿着物品的小孩就离开圆圈,游戏进行至只剩下一个小孩。

图1 六人传土豆游戏

        现在,我们也将热土豆问题称作Josephus问题。这个故事是关于公元1世纪著名历史学家Flavius Josephus 的,传说在犹太民族反抗罗马统治的战争中,Josephus 和他的39个同胞在一个洞穴中与罗马人相对抗。当注定的失败即将来临之时,他们决定宁可死也不投降罗马。于是他们围成一个圆圈,其中一个人被指定为第一位然后他们按照顺时针进行计数,每数到第七个人就把他杀死。传说中Josephus 除了熟知历史之外还是一个精通于数学的人。他迅速找出了那个能留到最后的位置。最后一刻,他没有选择自杀而是加入了罗马的阵营。这个故事还有许多不同的版本。有些是以三为单位进行计数,有些则是让最后一个留下的骑马逃走。但不管是哪个版本,其核心原理都是一致的。

        求解思路:1)模拟程序采用队列来存放所有参加游戏的人名,按照传递土豆方向从队首排到队尾;游戏时,队首始终是持有土豆的人。2)模拟游戏开始,只需要将队首的人出队,随即再到队尾入队,算是土豆的一次传递;传递了num次后,将队首的人移除,不再入队如此反复,直到队列中剩余1人。

图2 用队列模拟热土豆问题

参考代码:

import Queue

def hot_potato(namelist, nums):
    sim_queue = queue.Queue()
    for name in namelist:
        sim_queue.enqueue(name)
    
    while sim_queue.size() > 1:
        for _ in range(nums):
            sim_queue.enqueue(sim_queue.dequeue())
        sim_queue.dequeue()
    return sim_queue.dequeue()


print(hot_potato(["Bill", "David", "Susan", "Jane", "Kent", "Brad"], 7))

3.2 回文词判定

        一个能用双端队列数据结构轻松解决的问题是经典的“回文词”问题。回文词指的是正读和反读都一样的词,如:radar、toot 和madam。我们想要编写一个算法来检查放入的字符串是否为回文词。

        这个问题的解决方案是用一个双端队列来存储这个字符串。我们遍历这个字符串并把它的每个字母添加到双端队列的尾端。现在这个双端队列看起来非常像一个普通队列,但我们可以利用双端队列两端的对称性。双端队列的首端用来存储第一个字符,尾端用来存储最后一个字符。(如下图所示)

import Deque

def palchecker(aString):
    chardeque = Deque()
    for ch in aString:
        chardeque.addRear(ch)
    stillEqual = True
    
    while chardeque.size() > 1 and stillEqual:
        first = chardeque.removeFront()
        last = chardeque.removeRear()
        if first != last:
            stillEqual = False

    return stillEqual


print(palchecker("lsdkjfskf"))
print(palchecker("radar"))

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

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

相关文章

头歌作业之排序1、2、3、4

(PS:直接拿的友友zy的) 一个不知名大学生,江湖人称菜狗 original author: jacky Li Email : 3435673055qq.com Time of completion:2023.1.1 Last edited: 2023.1.1 目录 (PS:直接拿的友友的&a…

SCI论文解读复现【NO.2】基于注意机制的YOLOv5改进算法在行星图像中的应用(代码已复现)

此前出了目标检测算法改进专栏,但是对于应用于什么场景,需要什么改进方法对应与自己的应用场景有效果,并且多少改进点能发什么水平的文章,为解决大家的困惑,此系列文章旨在给大家解读发表高水平学术期刊中的SCI论文&am…

EMNLP22提示模板生成:GPS: Genetic Prompt Search for Efficient Few-shot Learning

GPS: Genetic Prompt Search for Efficient Few-shot Learning 1 简介 Genetic Prompt Search (GPS) 通过提示改进少样本学习,它利用遗传算法自动搜索高性能提示 遗传提示搜索 (GPS) 算法,该算法使用生成模型逐渐改变提示,并根据它们在小型…

C语言网刷题记录

作者:会敲代码的Steve 座右铭:博学笃志,切问静思。 大家好久不见啊,一看时间我已经好久没发文章了,最近在刷OJ题和学习;就没那么多心思把时间花在写文章上了,我对此感到很抱歉,本文呢…

int8,FLOPS,FLOPs,TOPS 等具体含义

1、定义 算力的计量单位FLOPS(Floating-point operations per second),FLOPS表示每秒浮点的运算次数。具体使用时,FLOPS前面还会有一个字母常量,例如TFLOPS、PFLOPS。这个字母T、P代表次数,T代表每秒一万亿…

Linux学习笔记——MySQL数据库管理系统安装部署

5.1、MySQL数据库管理系统安装部署 5.1.1、简介 1、MySQL简介 MySQL数据库管理系统(后续简称MySQL),是一款知名的数据库系统,其特点是:轻量、简单、功能丰富。 MySQL数据库可谓是软件行业的明星产品,无…

xilinx ZYNQ 7000 AXI GPIO

.0AXI GPIO 第一部分 PS 和 PL之间的通讯有一个接口称为AXI。AXI总线具体的内容这边不去深究,可以理解为一种特殊协议的通讯方式。 AXI GPIO是什么意思? PL是FPGA它可以做成任何你想要的东西,做一个GPIO外设当然是可以的。 如上图所示&…

DoIP协议从入门到精通——通信建立

在DoIP专栏中,关于DoIP文章,主要讲述从车辆物理连接、车辆声明、车辆通信激活(Routine Activation)和诊断通信几个步骤。 本文介绍了Tester与车辆获取物理连接、车辆声明自身信息后接下来需要操作的就是本文所要分享的内容:Tester与车辆控制器的通信建立。 一、通信模式…

记一次堆外内存泄漏分析

文章目录1. 背景2. JVM 内存分布与分析2.1 JVM 内存分布2.2 堆外内存泄漏分析思路2.3 服务器 JVM 参数配置及实际内存分布2.4 JVM native 内存查看2.5 手动触发 Full GC3. 问题排查经历3.1 定位内存泄漏的位置及初步猜想1)定位 RES 区域存在内存泄漏2)分…

寒假每日一题W1D1——孤独的照片

题目描述 Farmer John 最近购入了 N 头新的奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。 奶牛目前排成一排,Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。 然而&…

一本通 1267:【例9.11】01背包问题(详细代码)

经典01背包问题 这里给你3种方法 目录 DFS 思路: 代码: DFS记忆化 思路: 代码: 动态规划 思路: 代码: DFS 时间复杂度 :O(2^n) 思路: DFS求出所有选法,再用…

Maven 之 依赖管理

目录 1、依赖传递 小案例: 2、可选依赖 3、 排除依赖 4、可选依赖和排除依赖的区别 我们开发一个工程需要用到大量得jar包,而这些jar 包就是我们所说得依赖,一个项目可以配置多个依赖。 1、依赖传递 我们来看一下今天用来演示的工程。…

Linux性能学习(1.4):CPU_如何查看CPU上下文切换参数

文章目录1 系统总体上下文参数2 进程的上下文切换参数3 其它参考资料:vmstat:一个标准的报告虚拟内存统计工具 在前面大致了解了上下文切换的相关知识,那么如何在系统中查看上下文切换相关的参数? 1 系统总体上下文参数 使用vm…

人工势场法路径规划算法(APF)

本文主要对人工势场法路径规划算法进行介绍,主要涉及人工势场法的简介、引力和斥力模型及其推导过程、人工势场法的缺陷及改进思路、人工势场法的Python与MATLAB开源源码等方面 一、人工势场法简介 人工势场法是由Khatib于1985年在论文《Real-Time Obstacle Avoidan…

WPF使用触发器需要注意优先级问题

总目录 文章目录总目录前言一、问题开始二、问题说明三、问题订正总结前言 WPF使用触发器需要注意优先级问题 一、问题开始 现在有个需求: 初始状态(未选中)的时候,CheckBox的Content 为 “乒乓球”,然后选中之后&am…

python机器学习《基于逻辑回归的预测分类》

前言: 本文所有代码均在阿里天池实验室运行,本机的jupyter notebook也可运行。除此之外,还需要导入numpy,matplotlib,sklearn,seaborn包。每期文章前面都会有环境搭建说明。文中的讲解知识点均是按照从上往下讲解,将一些平常未接触…

⼯⼚⽅法模式

⼯⼚⽅法模式 ⼯⼚⽅法模式,属于创建者模式中的一种,这类模式提供创建对象的机制, 能够提升已有代码的灵活性和可复⽤性。 创建者模式包括:⼯⼚⽅法、抽象⼯⼚、⽣成器、原型、单例,这5类。 1.⼯⼚⽅法模式介绍 ⼯⼚…

LaoCat带你认识容器与镜像(二【一章】)

系列二章,祝大家新的一年事事顺心,想要的一定都实现。 本章内容 使用Docker镜像。 本文实操全部基于Ubuntu 20.04 一、使用Docker镜像 镜像(image)是Docker三大核心概念中最重要的,Docker运行容器前需要本地存在对应得…

在wsl下开发T113的主线linux(5)-构建ubi文件系统

接下来是构建文件系统,这里使用最新的buildroothttps://buildroot.org/download.htmlhttps://buildroot.org/download.html tar xf buildroot-2022.11.tar.gz cd buildroot-2022.11 make menuconfig 配置目标指令集类型 配置外部自定义编译器 配置生成文件系统类型…

数据结构和算法--算法与数据结构的概述、简单排序

目录 算法 算法概述 算法复杂度 数据结构 数据结构的概述 物理结构 逻辑结构 简单排序 1.选择排序 1.1算法描述 1.2算法实现 2冒泡排序 2.1算法描述 2.2算法实现 3插入排序 3.1算法描述 3.2算法实现 三种算法的比较 算法 算法概述 算法是一系列程序指令&am…