iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python双端队列怎么实现
  • 432
分享到

Python双端队列怎么实现

2023-06-29 18:06:13 432人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

这篇文章主要介绍了python双端队列怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python双端队列怎么实现文章都会有所收获,下面我们一起来看看吧。0. 学习目标双端队列是另一个线性数据结构。虽然它

这篇文章主要介绍了python双端队列怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python双端队列怎么实现文章都会有所收获,下面我们一起来看看吧。

Python双端队列怎么实现

0. 学习目标

双端队列是另一个线性数据结构。虽然它也是一种受限线性表,但与栈和队列不同的是,双端队列的限制很少,它的基本操作也是线性表操作的子集,但从数据类型的角度来讲,它们与线性表又有着巨大的不同。本节将介绍双端队列的定义及其不同实现,并且给出双端队列的一些实际应用。
通过本节学习,应掌握以下内容:

  • 双端队列的基本概念及不同实现方法

  • 双端队列基本操作的实现及时间复杂度

  • 利用双端队列的基本操作实现复杂算法

1. 双端队列的基本概念

1.1 双端队列的基本概念

双端队列 (double-end queue, deque) 也是插入和删除操作分别被限制在序列两端的线性表,但与栈和队列不同的是,双端队列的限制很少,对于双端队列而言,队尾 (rear) 和队头 (front) 均允许插入元素和删除元素。新元素既可以被添加到队头, 也可以被添加到队尾。同理,已有的元素也能从任意一端移除。某种意义上,可以认为双端队列是栈和队列的结合。

Python双端队列怎么实现

尽管双端队列有栈和队列的很多特性,但是它并不要求按照这两种数据结构所限定的 LIFO 原则和 FIFO 原则操作元素。

1.2 双端队列抽象数据类型

除了添加和移除元素外,双端队列还具有初始化、判队空和求队长度等辅助操作。具体而言,双端队列的抽象数据类型定义如下:

 基本操作:
  1. __itit__(): 初始化双端队列
   创建一个空双端队列
  2. size(): 求取并返回双端队列中所含元素的个数 n
   若双端队列为空,则返回整数0
  3. isempty(): 判断是否为空双端队列
   判断双端队列中是否存储元素
  4. addfront(data): 双端队列队头添加元素
   将元素 data 插入队头
  5. addrear(data): 双端队列队尾添加元素
   将元素 data 插入队尾
  6. removefront(): 删除双端队列队头元素
   删除并返回队头元素
  7. removerear(): 删除双端队列队尾元素
   删除并返回队尾元素

2. 双端队列的实现

和普通队列一样,双端队列同样有顺序存储和链式存储两种存储表示方式。

2.1 顺序双端队列的实现

类似于顺序队列,双端队列的顺序存储结构利用一组地址连续的存储单元依次存放从双端队列头到双端队列尾的元素,同时需要用两个指针 frontrear 分别指示队列头元素和队列尾元素的位置。初始化空双端队列时,front=rear=0,当元素入队时,rear 加 1,而元素出队时,front 加 1,同时为了重复利用空闲空间,我们将顺序双端队列假设尾环状空间,最后一个空间和第一个空间视为连续空间(具体原因参考<顺序队列>):

Python双端队列怎么实现

同样顺序双端队列可以是固定长度和动态长度,当双端队列满时,定长顺序双端队列会抛出双端队列满异常,动态顺序双端队列则会动态申请空闲空间。

2.1.1 双端队列的初始化

顺序双端队列的初始化需要 4 部分信息:deque 列表用于存储数据元素,max_size 用于存储 queue 列表的最大长度,以及 frontrear 分别用于记录队头元素和队尾元素的索引

class Deque:    def __init__(self, max_size=6):        self.max_size = max_size        self.deque = [None] * self.max_size        self.front = 0        self.rear = 0
2.1.2 求双端队列长度

由于 frontrear 分别用于记录队头元素和队尾元素的索引,因此我们可以方便的计算出双端队列的长度;同时我们需要考虑双端队列为循环队列,front 可能大于 rear,不能直接通过 rear-front,我们需要利用公式计算解决此问题:

Python 实现如下:

    def size(self):        return (self.rear-self.front+self.max_size) % self.max_size
2.1.3 判双端队列空

根据 frontrear 的值可以方便的判断双端队列是否为空:

    def isempty(self):        return self.rear==self.front
2.1.4 判双端队列满

根据 frontrear 的值可以方便的判断双端队列是否还有空余空间:

    def isfull(self):        return ((self.rear+1) % self.max_size == self.front)
2.1.5 双端队列队头和队尾添加元素

添加元素时,需要首先判断双端队列中是否还有空闲空间,然后根据双端队列为定长顺序双端队列或动态顺序双端队列,添加元素操作稍有不同:
[定长顺序双端队列的添加元素操作] 如果队满,则引发异常:

    # 注意队头和队尾修改索引的添加元素的不同顺序    def addrear(self, data):        if not self.isfull():            self.deque[self.rear] = data            self.rear = (self.rear+1) % self.max_size        else:            raise IndexError("Full Deque Exception")        def addfront(self, data):        if self.isfull():            self.resize()        if self.isempty():            # 当双端队列            self.deque[self.rear] = data            self.rear = (self.rear+1) % self.max_size        else:            self.front = (self.front - 1 + self.max_size) % self.max_size            self.deque[self.front] = data

[动态顺序双端队列的添加元素操作] 如果双端队列满,则首先申请新空间,然后再执行添加操作:

    def resize(self):        new_size = 2 * self.max_size        new_deque = [None] * new_size        d = new_size - self.max_size        for i in range(self.max_size):            new_deque[(self.front+i+d) % new_size] = self.deque[(self.front+i) % self.max_size]        self.deque = new_deque        self.front = (self.front+d) % new_size        self.max_size = new_size            # 注意队头和队尾修改索引的添加元素的不同顺序    def addrear(self, data):        if self.isfull():            self.resize()        self.deque[self.rear] = data        self.rear = (self.rear+1) % self.max_size    def addfront(self, data):        if self.isfull():            self.resize()        self.front = (self.front - 1 + self.max_size) % self.max_size        self.deque[self.front] = data

与动态顺序队列类似,我们同样需要考虑复制之后的索引,否则可能出现存在不能用的空闲空间:

Python双端队列怎么实现

添加元素的时间复杂度为O(1)。虽然当动态顺序双端队列满时,原双端队列中的元素需要首先复制到新双端队列中,然后添加新元素,但参考《顺序表及其操作实现》中顺序表追加操作的介绍,由于 n 次添加元素操作的总时间T(n) 与O(n) 成正比,因此其摊销时间复杂度可以认为O(1)。

2.1.6 删除队头或队尾的元素

若双端队列不空,则删除并返回指定端元素:

    # 注意队头和队尾修改索引的删除元素的不同顺序    def removefront(self):        if not self.isempty():            result = self.deque[self.front]            self.front = (self.front+1) % self.max_size            return result        else:            raise IndexError("Empty Deque Exception")        def removerear(self):        if not self.isempty():            self.rear = (self.rear - 1 + self.max_size) % self.max_size            result = self.deque[self.rear]            return result        else:            raise IndexError("Empty Deque Exception")

2.2 链双端队列的实现

双端队列的另一种存储表示方式是使用链式存储结构,因此也常称为链双端队列,其中 addfront 操作和 addrear 操作分别是通过在链表头部和尾部插入元素来实现的,而 removefront 操作和 removerear 操作分别是通过从头部和尾部删除结点来实现的。为了降低在尾部删除结点的时间复杂度,接下来基于双向链表实现双端队列。

Python双端队列怎么实现

2.2.1 双端队列结点

双端队列的结点实现与双向链表并无差别:

class node:    def __init__(self, data=None):        self.data = data        self.next = None    def __str__(self):        return str(self.data)
2.2.2 双端队列的初始化

双端队列的初始化函数中,使其队头指针 front 和队尾指针 rear 均指向 None,并初始化双端队列长度:

class Deque:    def __init__(self):        self.front = None        self.rear = None        self.num = 0
2.2.3 求双端队列长度

返回 num 的值用于求取双端队列的长度,如果没有 num 属性,则需要遍历整个链表才能得到双端队列长度:

    def size(self):        return self.num
2.2.4 判双端队列空

根据双端队列的长度可以很容易的判断其是否为空双端队列:

    def isempty(self):        return self.num <= 0
2.2.5 添加元素

双端队列添加元素时,可以在队尾或队头插入新元素,因此需要修改 rearfront 指针,并且同时也要修改结点的 nextprevious 指针;如果添加元素前双端队列为空,还需要进行相应处理:

    def addrear(self, data):        node = Node(data)        # 如果添加元素前双端队列为空,则添加结点时,需要将front指针也指向该结点        if self.front is None:            self.rear = node            self.front = node        else:            node.previous = self.rear            self.rear.next = node            self.rear = node        self.num += 1        def addfront(self, data):        node = Node(data)        # 如果添加元素前双端队列为空,则添加结点时,需要将rear指针也指向该结点        if self.rear is None:            self.front = node            self.rear = node        else:            node.next = self.front            self.front.previous = node            self.front = node        self.num += 1
2.2.6 删除元素

若双端队列不空,可以从删除队头或队尾元素并返回,删除操作需要更新队头指针 front 以及尾指针 rear,同时也要修改结点的 nextprevious 指针,若出队元素尾队中最后一个结点,还需要进行相应处理:

    def removefront(self):        if self.isempty():            raise IndexError("Empty Queue Exception")        result = self.front.data        self.front = self.front.next        self.num -= 1        if self.isempty():            self.rear = self.front        else:            # 若删除操作完成后,双端队列不为空,将 front 指针的前驱指针指向 None            self.front.previous = None        return result        def removerear(self):        if self.isempty():            raise IndexError("Empty Queue Exception")        result = self.rear.data        self.rear = self.rear.previous        self.num -= 1        if self.isempty():            self.front = self.rear        else:            # 若删除操作完成后,双端队列不为空,将 rear 指针的后继指针指向 None            self.rear.next = None        return result

2.3 双端队列的不同实现对比

双端队列的不同实现对比与栈的不同实现类似,可以参考《栈及其操作实现》。

3. 双端队列应用

接下来,我们首先测试上述实现的双端队列,以验证操作的有效性,然后利用实现的基本操作来解决实际算法问题。

3.1 顺序双端队列的应用

首先初始化一个顺序双端队列 deque,然后测试相关操作:

# 初始化一个最大长度为5的双端队列dq = Deque(5)print('双端队列空?', dq.isempty())for i in range(3):    print('队头添加元素:', 2*i)    dq.addfront(2*i)    print('队尾添加元素:', 2*i+1)    dq.addrear(2*i+1)print('双端队列长度为:', dq.size())for i in range(3):    print('队尾删除元素:', dq.removerear())    print('队头删除元素:', dq.removefront())print('双端队列长度为:', dq.size())

测试程序输出结果如下:

双端队列空? True队头添加元素: 0队尾添加元素: 1队头添加元素: 2队尾添加元素: 3队头添加元素: 4队尾添加元素: 5双端队列长度为: 6队尾删除元素: 5队头删除元素: 4队尾删除元素: 3队头删除元素: 2队尾删除元素: 1队头删除元素: 0双端队列长度为: 0

3.2 链双端队列的应用

首先初始化一个链双端队列 queue,然后测试相关操作:

# 初始化新队列dq = Deque()print('双端队列空?', dq.isempty())for i in range(3):    print('队头添加元素:', i)    dq.addfront(2*i)    print('队尾添加元素:', i+3)    dq.addrear(2*i+1)print('双端队列长度为:', dq.size())for i in range(3):    print('队尾删除元素:', dq.removerear())    print('队头删除元素:', dq.removefront())print('双端队列长度为:', dq.size())

测试程序输出结果如下:

双端队列空? True队头添加元素: 0队尾添加元素: 3队头添加元素: 1队尾添加元素: 4队头添加元素: 2队尾添加元素: 5双端队列长度为: 6队尾删除元素: 5队头删除元素: 4队尾删除元素: 3队头删除元素: 2队尾删除元素: 1队头删除元素: 0双端队列长度为: 0

3.3 利用双端队列基本操作实现复杂算法

[1] 给定一字符串 string (如:abamaba),检查其是否为回文。

使用双端队列可以快速检查一字符串是否为回文序列,只需要将字符串中字符依次入队,然后从双端队列两端依次弹出元素,对比它们是否相等:

def ispalindrome(string):    deque = Deque()    for ch in string:        deque.addfront(ch)    flag = True    while deque.size() > 1 and flag:        ch2 = deque.removefront()        ch3 = deque.removerear()        if ch2 != ch3:            flag = False    return flag

验证算法有效性:

print('abcba是否为回文序列:', ispalindrome('abcba'))print('charaahc是否为回文序列:', ispalindrome('charaahc'))

结果输出如下:

abcba是否为回文序列: Truecharaahc是否为回文序列: False

关于“Python双端队列怎么实现”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Python双端队列怎么实现”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网Python频道。

--结束END--

本文标题: Python双端队列怎么实现

本文链接: https://www.lsjlt.com/news/326164.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python双端队列怎么实现
    这篇文章主要介绍了Python双端队列怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python双端队列怎么实现文章都会有所收获,下面我们一起来看看吧。0. 学习目标双端队列是另一个线性数据结构。虽然它...
    99+
    2023-06-29
  • Python双端队列deque的实现
    目录前言基本用法填充线程安全旋转限制双端队列大小前言 双端队列deque支持从任意一端增加和删除元素。其中,栈和队列就是双端队列的退化形式,它们的输入输出被限制在某一端。 基本用法 ...
    99+
    2024-04-02
  • javascript实现双端队列
    本文实例为大家分享了javascript实现双端队列的具体代码,供大家参考,具体内容如下 1.双端队列 双端队列是一种允许我们同时从前端和后端添加和移除元素的特殊队列 2.双端队列...
    99+
    2024-04-02
  • Python双端队列怎么实现回文检测
    本文小编为大家详细介绍“Python双端队列怎么实现回文检测”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python双端队列怎么实现回文检测”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、双端队列双端队列 ...
    99+
    2023-06-26
  • Python双端队列实现回文检测
    目录一、双端队列二、回文检测补充一、双端队列 双端队列 Deque 是一种有次序的数据集,跟队列相似,其两端可以称作"首" 和 "尾"端,但 ...
    99+
    2024-04-02
  • php怎么实现双向队列
    在PHP中,可以使用数组来实现双向队列。下面是一个示例代码: class Deque { private $deque; ...
    99+
    2023-10-22
    php
  • python中如何定义栈、队列及双端队列
    这篇文章给大家分享的是有关python中如何定义栈、队列及双端队列的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1.线性数据结构的定义我们首先学习 4 种简单而强大的数据结构。栈、队列、双端队列和列表都是有序的数...
    99+
    2023-06-22
  • python数据结构之栈、队列及双端队列
    目录1.线性数据结构的定义2.栈2.1栈的定义2.2栈的数据类型2.3用python实现栈2.4栈的应用3.队列3.1队列的定义3.2队列抽象数据类型3.3用python实现队列3....
    99+
    2024-04-02
  • python如何实现有最大长度的双端队列
    小编给大家分享一下python如何实现有最大长度的双端队列,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!有最大长度的双端队列&g...
    99+
    2024-04-02
  • python双端队列的原理是什么
    这篇文章主要介绍python双端队列的原理是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!python的数据类型有哪些python的数据类型:1. 数字类型,包括int(整型)、long(长整型)和float(浮...
    99+
    2023-06-14
  • C++图搜索算法之双端队列广搜怎么实现
    这篇文章主要介绍“C++图搜索算法之双端队列广搜怎么实现”,在日常操作中,相信很多人在C++图搜索算法之双端队列广搜怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++图搜索算法之双端队列广搜怎么实现...
    99+
    2023-07-02
  • Python栈和队列怎么实现
    这篇文章主要介绍“Python栈和队列怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python栈和队列怎么实现”文章能帮助大家解决问题。一、栈概述栈(st...
    99+
    2024-04-02
  • Python中什么是双向队列
    今天就跟大家聊聊有关Python中什么是双向队列,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。python主要应用领域有哪些1、云计算,典型应用OpenStack。2、WEB前端开发...
    99+
    2023-06-14
  • Python中怎么用队列实现栈
    这篇文章给大家介绍Python中怎么用队列实现栈,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。题目:使用队列实现栈的下列操作:push(x) – 元素 x 入栈pop() – 移除栈顶元素top() – 获取栈顶元素e...
    99+
    2023-06-02
  • 浅谈C++STL之双端队列容器
    目录概述插入元素遍历删除元素概述 deque块在头部和尾部都可以插入和删除。而不需要移动任何元素,而不需要移动其他元素(使用push_back()方法在尾部插入元素,会扩张队列,而使...
    99+
    2024-04-02
  • 怎么理解php双向队列
    这篇文章主要讲解了“怎么理解php双向队列”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解php双向队列”吧!双向队列是指一种具有队列和栈的性质的数据结构。双向队列中的元素可以从两端弹...
    99+
    2023-06-25
  • Python数据结构与算法的双端队列详解
    目录什么是双端队列​​用Python实现双端队列运用双端队列构建回文检测器总结什么是双端队列​ 双端队列是与队列类似的有序集合。它有一前、一后两端,元素在其中保持自己的位置。与队列不...
    99+
    2024-04-02
  • Golang中怎么实现队列
    本篇内容介绍了“Golang中怎么实现队列”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是队列队列是一种特殊的线性数据结构,它遵循先进先...
    99+
    2023-07-05
  • 简单介绍python的双向队列
    介绍   大家都知道利用 .append 和 .pop 方法,我们可以把列表当作栈或者队列来用(比如,把 append 和 pop(0) 合起来用,就能模拟栈的“先进先出”的特点)。但是删除列表的第一个元素(抑或是在第一个元素之前添加一个...
    99+
    2023-01-30
    队列 双向 简单
  • 什么是php双向队列
    这篇文章主要讲解了“什么是php双向队列”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“什么是php双向队列”吧!php双向队列是指一种具有队列和栈的性质的数据结构;双向队列中的元素可以从两端...
    99+
    2023-06-25
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作