python数据结构与算法-04_队列

队列和栈

前面讲了线性和链式结构,如果你顺利掌握了,下边的队列和栈就小菜一碟了。因为我们会用前两章讲到的东西来实现队列和栈。
之所以放到一起讲是因为这两个东西很类似,队列是先进先出结构(FIFO, first in first out),
栈是后进先出结构(LIFO, last in first out)。

生活中的数据结构:

  • 队列。没错就是咱平常排队,第一个来的第一个走

本章我们详细讲讲常用的队列

队列 Queue

这里卖个关子,如果你熟悉了上两节讲的内容,这里你会选取哪个数据结构作为队列的底层存储?
还记得第一章讲的如何实现 ADT 吗?我视频了说了三个注意事项:

  • 1.如何选用恰当的数据结构作为存储?
  • 2.选取的数据结构能否满足 ADT 的功能需求
  • 3.实现效率如何?

我们先来看看 list 可以不?对照这个三个需求,看看能否满足:

  • 1.我们选择了 list
  • 2.看起来队列需要从头删除,向尾部增加元素,也就是 list.pop(0) 和 list.append(element)
  • 3.嗯,貌似 list.pop(0) 会导致所有其后所有元素向前移动一个位置,O(n)复杂度。append 平均倒是O(1),但是如果内存不够还要重新分配内存。

你看,使用了 list 的话频繁 pop(0) 是非常低效的。(当然list 实现还有另一种方式就是插入用 list.insert(0, item),删除用list.pop())

脑子再转转, 我们第二章实现了 链表 LinkedList,看看能否满足要求:

  • 1.这里选择 LinkedList
  • 2.删除头元素 LinkedList.popleft(),追加 append(element)。都可以满足
  • 3.哇欧,这两个操作都是 O(1) 的,完美。

好, 就用 LinkedList 了,我们开始实现,具体看视频。这次实现我们还将演示自定义异常和测试异常。

用数组实现队列

难道用数组就不能实现队列了吗?其实还是可以的。只不过数组是预先分配固定内存的,所以如果你知道了队列的最大长度,也是
可以用数组来实现的。

想象一下,队列就俩操作,进进出出,一进一出,pop 和 push 操作。
似乎只要两个下标 head, tail 就可以了。 当我们 push 的时候赋值并且前移 head,pop 的时候前移 tail 就可以了。你可以在纸上
模拟下试试。列队的长度就是 head-pop,这个长度必须不能大于初始化的最大程度。

如果 head 先到了数组末尾咋办?重头来呗,只要我们保证 tail 不会超过 head 就行。

head = 0,1,2,3,4 … 0,1,2,3,4 …

重头再来,循环往复,仿佛一个轮回。。。。
怎么重头来呢?看上边数组的规律你如果还想不起来用取模,估计小学数学是体育老师教的。

maxsize = 5
for i in range(100):
    print(i % maxsize)

在这里插入图片描述

我们来实现一个空间有限的循环队列。ArrayQueue,它的实现很简单,但是缺点是需要预先知道队列的长度来分配内存。

双端队列 Double ended Queue

看了视频相信你已经会实现队列了,你可能还听过双端队列。上边讲到的队列 队头出,尾尾进,我们如果想头部和尾巴都能进能出呢?
这就是双端队列了,如果你用过 collections.deque 模块,就是这个东西。他能高效在两头操作。

假如让你实现你能想起来嘛?
似乎我们需要一个能 append() appendleft() popleft() pop() 都是 O(1) 的数据结构。

上边我们实现 队列的 LinkedList 可以吗?貌似就差一个 pop() 最后边的元素无法实现了。
对,我们还有双端链表。它有这几个方法:

  • append
  • appendleft
  • headnode()
  • tailnode()
  • remove(node) # O(1)

啊哈,似乎删除头尾都可以啦,而且都是 O(1) 的,完美。
交给你一个艰巨的任务,实现双端队列 Deque() ADT。你可以参考前几章的任何代码,挑战一下这个任务,别忘记写单元测试呦。当然如果没想出来也没关系,后边我们实现栈的时候还会用到它,那里我们会实现这个代码。

源码

# -*- coding: utf-8 -*-


# NOTE: 从 array_and_list 第一章拷贝的代码
class Array(object):

    def __init__(self, size=32):
        self._size = size
        self._items = [None] * size

    def __getitem__(self, index):
        return self._items[index]

    def __setitem__(self, index, value):
        self._items[index] = value

    def __len__(self):
        return self._size

    def clear(self, value=None):
        for i in range(len(self._items)):
            self._items[i] = value

    def __iter__(self):
        for item in self._items:
            yield item


class FullError(Exception):
    pass


class ArrayQueue(object):
    def __init__(self, maxsize):
        self.maxsize = maxsize
        self.array = Array(maxsize)
        self.head = 0
        self.tail = 0

    def push(self, value):
        if len(self) >= self.maxsize:
            raise FullError('queue full')
        self.array[self.head % self.maxsize] = value
        self.head += 1

    def pop(self):
        value = self.array[self.tail % self.maxsize]
        self.tail += 1
        return value

    def __len__(self):
        return self.head - self.tail


def test_queue():
    import pytest    # pip install pytest
    size = 5
    q = ArrayQueue(size)
    for i in range(size):
        q.push(i)

    with pytest.raises(FullError) as excinfo:   # 我们来测试是否真的抛出了异常
        q.push(size)
    assert 'full' in str(excinfo.value)

    assert len(q) == 5

    assert q.pop() == 0
    assert q.pop() == 1

    q.push(5)

    assert len(q) == 4

    assert q.pop() == 2
    assert q.pop() == 3
    assert q.pop() == 4
    assert q.pop() == 5

    assert len(q) == 0

思考题

  • 你能用 python 的 deque 来实现 queue ADT 吗?
  • 哪些经典算法里用到了队列呢?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

android studio开发flutter应用,使用mumu模拟器调试软件

安装好mumu模拟器,先打开网易mumu模拟器的开发者模拟。系统应用 > 设置 > 关于手机 > 版本号 多点击几次调出开发者模式: 然后在android studio中刷新设备列表,就能看到新设备了: 如何确定这个设备就是你的mumu模拟器呢…

2012年11月10日 Go生态洞察:Go语言三周年回顾

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

预览PDF并显示当前页数

这里写目录标题 步骤实例实例效果图 步骤 1.安装依赖 npm install --save vue-pdf2.在需要的页面&#xff0c;引入插件 import pdf from vue-pdf3.使用 单页pdf可以直接使用 <pdf :src"获取到的pdf地址"></pdf>多页pdf通过循环实现 html标签部分 &l…

电子零部件工厂的WMS系统:业务特点、产品特点与优势

一、电子零部件工厂的业务特点 电子零部件工厂的业务涉及各种电子元器件的生产、组装和配送。其业务特点包括&#xff1a; 高度复杂性&#xff1a;电子零部件工厂的生产流程涉及多种原材料、半成品和成品&#xff0c;每种产品都有不同的规格、属性及存储要求。 严格的质量控…

基于Rabbitmq和Redis的延迟消息实现

1 基于Rabbitmq延迟消息实现 支付时间设置为30&#xff0c;未支付的消息会积压在mq中&#xff0c;给mq带来巨大压力。我们可以利用Rabbitmq的延迟队列插件实现消息前一分钟尽快处理 1.1定义延迟消息实体 由于我们要多次发送延迟消息&#xff0c;因此需要先定义一个记录消息…

Jenkins 构建CICD

GitLab GitLab安装 https://gitlab.cn/install/?versionce CentOS 下安装 1. 安装和配置必须的依赖项 在 CentOS 7上&#xff0c;下面的命令也会在系统防火墙中打开 HTTP、HTTPS 和 SSH 访问。这是一个可选步骤&#xff0c;如果您打算仅从本地网络访问极狐GitLab&#xf…

【极客时间-系列教程】Vim 实用技巧必知必会-基本概念和基础命令:应对简单的编辑任务

vim很强大&#xff0c;但它的入门确实是比较高&#xff0c;对于初学者来说&#xff0c;怎么退出都是一件很难的事情&#xff0c; 不管你有没有遇到过&#xff0c;反正我是遇到过退出比较难的问题 首先介绍几个常用的命令和按键 :q! 退出不保存:w 写入不退出:r 读文件:wq 写入…

Android面试官の小抄,可能是东半球最好的

面试官的小抄&#xff0c;Android面试&进阶一网打尽&#xff0c;让一部分人先学起来 背景 作为一名客户端开发者&#xff0c;能够明显的感觉到小程序这些年对原生市场带来的压迫感&#xff0c;比如现在的创业公司都是小程序探路&#xff0c;成熟了再推进客户端&#xff0…

用递归解饮料换购

乐羊羊饮料厂正在举办一次促销优惠活动。乐羊羊C型饮料&#xff0c;凭3个瓶盖可以再换一瓶C型饮料&#xff0c;并且可以一直循环下去&#xff0c;但不允许赊账。 请你计算一下&#xff0c;如果小明不浪费瓶盖&#xff0c;尽量地参加活动&#xff0c;那么&#xff0c;对于他初始…

小程序与公众号下发统一消息接口返回45109

根据微信官方通告&#xff0c;自 2023 年 9 月 20 日起&#xff0c;下发统一消息接口将被收回&#xff0c;返回45109。链接见 小程序与公众号下发统一消息接口调整通知 | 微信开放社区各位开发者&#xff1a;下发统一消息 接口曾支持小程序与公众号统一的模板消息下发。由于小程…

揭密,这个微信群机器人的所有秘密在这里

技术长久不用就废了&#xff0c;我想把软件开发技术重新捡拾起来。 咱们“一起学英语”群已有三年时光&#xff0c;群里很多朋友互帮互助走到了今天。可是&#xff0c;即使再好玩的英语话题&#xff0c;也有谈腻的时候。 群里是不是应该引入一点好玩的东西&#xff1f; 人工智能…

51单片机+DS1302设计一个电子钟(LCD1602显示时间)

一、前言 电子钟是一种能够准确显示时间的设备&#xff0c;广泛应用于家庭、办公场所和公共场所&#xff0c;为人们提供了方便和准确的时间信息。本项目设计一个基于51单片机的电子钟&#xff0c;使用DS1302作为RTC时钟芯片&#xff0c;LCD1602作为显示屏&#xff0c;并通过串…

亚马逊、Shein、lazada自养号测评如何解决支付和环境问题?

年底旺季&#xff0c;平台风控都会大规模持续升级&#xff0c;针对风控升级如果测评环境没有进行相对应的更新可能会导致大批量砍单&#xff0c;或者F号&#xff0c;严重的店铺还会被关联。有人以为是支付卡的问题&#xff0c;也有人觉得是IP被关联了。其实他们讲的也没错&…

【万字长文】前端性能优化实践 | 京东云技术团队

一、引言 从一个假死页面引发的思考&#xff1a; 作为前端开发&#xff0c;除了要攻克页面难点&#xff0c;也要有更深的自我目标&#xff0c;性能优化是自我提升中很重要的一环&#xff1b; 在前端开发中&#xff0c;会偶遇到页面假死的现象&#xff0c; 是因为当js有大量计算…

mysql 中with的用法(2)

with递归练习主要用于表里面包含父节点id之类的 查询出对应的省份和市。 建表 CREATE TABLE tb(id VARCHAR(3), pid VARCHAR(3), name VARCHAR(64));INSERT INTO tb VALUES(002, 0, 浙江省); INSERT INTO tb VALUES(001, 0, 广东省); INSERT INTO tb VALUES(003, 002, 衢州市…

史上最强AI芯片!英伟达H200震撼来袭!141 GB 超大显存,Llama2推理性能翻倍,老黄赢麻了!

原创 作者 | 王二狗英伟达又一次打了所有人措手不及&#xff01; 就在昨晚&#xff0c;老黄发布了新一代史上最强 AI芯片 NVIDIA HGX™ H200 。 141 GB 超大显存&#xff01;带宽增加 2.4 倍 H200 拥有141GB 显存&#xff01;相比之前的 H100和A100&#xff0c;容量几乎翻倍&…

SpringBoot整合Activiti7——定时器事件(九)

文章目录 定时器事件时间定义时间固定时间段时间周期 1.开始事件2.中间事件3.边界事件代码实现xml文件自定义服务任务监听器自定义用户任务监听器测试流程流程执行步骤 定时器事件 可以用在开始事件、中间事件、边界事件上&#xff0c;边界事件可以是中断和非中断边界事件 需要…

css实现元素四周阴影

前言 首先确定的是需要使用box-shadow这一属性 语法如下&#xff1a; box-shadow: h-shadow v-shadow blur spread color inset; h-shadow&#xff1a;表示水平方向上的阴影偏移量&#xff0c;必须指明&#xff0c;可以是正数、负数、0&#xff0c;如果为正数左方有阴影&…

安装MinGW并在codeblocks下使用

一、下载安装MinGW 1.下载MinGw安装器&#xff0c;下载地址 2. 安装 下载下来的知识一个安装器&#xff0c;我们双击安装会帮我们自动下载好相关文件 安装完成后会打开一个安装管理工具&#xff0c;在这个工具中我们选中想要安装的软件包然后安装到本地 选好以后在菜单栏选…