循环队列判断队空和队满_数据结构与算法——栈与队列(二)

59ec1f0d09cfe01753f890388e919383.png

(二) 队列

定义

和栈相似,队列也是一种特殊的线性表,跟数组的不同之处也体现在增删等操作上。队列的插入操作只能在队列的末尾进行,队列的删除操作只能在队头进行,队列是一种先进先出的线性表。用数组实现的队列叫链式队列,用链表实现的队列叫链式队列。

队列的基本操作

和栈相似,对于队列,插入数据只能在队尾进行,删除数据只能在队头进行,在队列中插入数据我们叫入队enqueue,删除队列中的数据我们叫出队dequeue。

同样的我们分别基于顺序队列和链式队列对他们的增加删除操作进行讨论。

链式队列

对于链式队列,在初始化的时候同样需要定义两个指针,front指针与rear指针指向队列的尾部。当队列为空的时候,front指针和rear指针都指向空链表的头部。在出队时,只需要将front指针指向当前节点的下一个节点即可。

4a7953c575bdf0c8e3638bb388e09858.png

链式队列的入队,只需要将队尾指针rear指向的节点的next指针指向要插入的新节点即可。

f92ec55c7b1f515dd59383a4277bae96.png
class Node():
    '''链表结构的Node节点'''
    def __init__(self, val, next = None):
        '''Node节点的初始化方法.
        参数:
            val:存储的数据
            next:下一个Node节点的引用地址
        '''
        self.val = val
        self.next = next

class LinkQueue():
    """链式队列"""
    def __init__(self):
        """链式队列初始化"""
        self.head, self.tail = None, None

    def enqueue(self, num):
        """入队
        参数:
            num: 入队的数值
        """
        node = Node(num)
        if self.tail:
            self.tail.next = node
        else:
            self.head = node
        self.tail = node
        return True

    def dequeue(self):
        """出队
        返回:
            队首的值
        """
        if self.head:
            num = self.head.val
            self.head = self.head.next
            if not self.head:
                self.tail = None
            return num
        return None

    def PrintAll(self):
        """打印队列
        返回:
            整个队列
        """
        if not self.head:
            return None
        res = []
        node = self.head
        while node:
            res.append(node.val)
            node = node.next
        return '->'.join('%s'%num for num in res)

顺序队列

对于顺序队列,在初始化的时候需要定义两个指针并且给出队列的大小,front指针指向队列头部,rear指针指向队列的尾部。当队列为空的时候,front指针与rear指针都指向数组下标为0的位置。在出队时,只需要将front指针向后移一位即可,因此顺序队列的出队时间复杂度为O(1)。

2724c7a622f6285ac13150743e969a08.png

对于顺序队列的入队操作,需要考虑队列是否已经满了的情况,如果rear指针已经指向数组的最后一个下标位置,此时需要判断,front指针是否经过出队操作后往后移动了,如果front指针不指向数组下标为0的位置,那么将front到rear指针之间的数据都移动到数组开头,然后front指针重新指向数组下标为0的位置,rear指针指向rear-front的位置。如果front指针指向数组下标为0的位置且rear指针指向数组最后一个位置,那么队列已经满了,此时则需要考虑扩容的问题。如果入队时的队列未满,且rear指针指向的位置不是数组尾部,那么入队的时间复杂度为O(1);如果队列未满且rear指针指向数组尾部,还有队列已满需要扩容这两种情况,由于涉及到数据的搬移,时间复杂度为O(n)。

0a8afb549bacf6ce5491e616a5b4b1a3.png

对于顺序队列的入队操作,像上面那种rear指针指向数组尾部但是数组前面是空的假溢出情况,通常有两种简单粗暴的解决方法:

(1)第一种是像上面那样的解决方法,消耗O(n)的时间复杂度进行数据搬移

(2)第二种是初始化队列的时候,申请足够大的内存空间确保数组不越界

class ArrayQueue():
    """顺序队列"""
    def __init__(self, capacity):
        """顺序队列的初始化
        参数:
            capacity: 顺序队列的大小
        """
        self.queue = []
        self.capacity = capacity
        self.head, self.tail = 0, 0

    def enqueue(self, num):
        """入队1
        参数:
            num: 入队的数值
        """
        if self.tail == self.capacity:
            return False
        self.queue.append(num)
        self.tail += 1
        return True

    def NewEnqueue(self, num):
        """入队2:队首有多余空间且队满的情况下,进行数据搬移后再入队
        参数:
            num: 入队的数值
        """
        if self.tail == self.capacity:
            if self.head == 0:
                return False
            for i in range(self.head, self.tail):
                self.queue[i - self.head] = self.queue[i]
            self.tail -= self.head
            self.head = 0
        self.queue[self.tail] = num
        self.tail += 1
        return True

    def dequeue(self):
        """出队
        返回:
            队首的值
        """
        if not self.queue:
            return False
        num = self.queue[0]
        self.head += 1
        return num

    def PrintAll(self):
        """打印队列
        返回:
            整个队列
        """
        if not self.queue:
            print(None)
            return False
        print(self.queue[self.head: self.tail])
        return True

对于第一种方法,由于当rear==n-1的时候,会有数据搬移,这点会影响到队列的入队操作性能;而对于第二种方法,由于不断的出列,数组前面会空出很多不使用的内存空间,这些空间也不被释放,会造成大量的内存空间浪费。

那么数组的越界问题有没有什么好的解决方法呢?接下来要说的循环队列,就是对这种问题的一种解决方法。

循环队列

我们将顺序队列的首尾相连就形成了一个环,如下图所示,可以看到队列的大小为8,front=4,rear= 7,当我们向队列中插入元素时,数据插入rear指向的位置并且rear往后移一位,这里要注意的是rear指针已经指向下标为7的位置了,所以当我们在rear处插入一个元素后,rear指针接下来会指向下标为6的位置。

5ddec4fd4706fbc94077a9367802c51f.png

上面是队列未满时的情况,如果队列已满,假设队列的情况如下图所示。

53db89016eaa7ddddc7ee7639f991653.png

我们可以看到rear指针指向的位置为空,也就是说我们的循环队列在使用的时候会浪费一个存储空间。

那么怎么样判断队满与队空的情况呢?首先是判断队空,跟普通的队列相同,当front==rear时,队列是空的;队满的判断条件与其他的队列不同,我们可以用两种方法来判断循环队列是否已满。

第一种:我们在初始化循环队列时,设置一个标志位flag和一个计数值count,最开始rear=front且flag=count=0,当我们插入一个数据时,判断count是否等于队列大小n-1,如果是的话那么已经队满无法插入数据且令flag=1,否则我们将数据插入到rear当前的位置并将rear移向下一位,count++;同样的删除数据时,head指向他的下一个位置并且count—。

第二种:通过前人的总结,队满的条件为(rear + 1) % n == front,直接用这个条件判断是否队满。

class CircularQueue():
    """用数组实现的循环队列"""
    def __init__(self, capacity):
        """顺序队列的初始化
                参数:
                    capacity: 顺序队列的大小
                """
        self.queue = []
        self.capacity = capacity + 1
        self.head, self.tail = 0, 0
​
    def enqueue(self, num):
        """入队1
        参数:
            num: 入队的数值
        """
        if (self.tail + 1) % self.capacity == self.head:
            return False
        self.queue.append(num)
        self.tail = (self.tail + 1) % self.capacity
        return True
​
    def dequeue(self):
        """出队
        返回:
            队首的值
        """
        if self.head != self.tail:
            num = self.queue[self.head]
            self.head = (self.head + 1) % self.capacity
            return num
​
    def PrintAll(self):
        """打印队列
        返回:
            整个队列
        """
        if self.tail >= self.head:
            return self.queue[self.head : self.tail]
        res = self.queue[self.head :] + self.queue[:self.tail - 1]
        return res

应用

1、约瑟夫问题

2、线程并发问题

weixin_39932330
关注 关注
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构算法——队列(二)
Jaeshn
10-16 590
(二) 队列 定义 和相似,队列也是一种特殊的线性表,跟数组的不同之处也体现在增删等操作上。队列的插入操作只能在队列的末尾进行,队列的删除操作只能在头进行,队列是一种先进先出的线性表。用数组实现的队列叫链式队列,用链表实现的队列叫链式队列队列的基本操作 和相似,对于队列,插入数据只能在尾进行,删除数据只能在头进行,在队列中插入数据我们叫入enqueue,删除队列中的数据我们叫出dequeue。 同样的我们分别基于顺序队列和链式队列对他们的增加删除操作进行讨论。 链式队列 对于链式队列,在初
C++ STL list 遍历删除出错解决方案
09-01
主要介绍了C++ STL list 遍历删除出错解决方案的相关资料,这里对出错进行分析,并给出正确的解决方法,需要的朋友可以参考下
循环队列判断
热门推荐
QAQ
04-02 6万+
在引用循环队列前,我们需要了解队列是如何线性实现的。 简单地讲,便是当队列时,front = rear = 0,每当插入元素尾指针+1,删除元素是头指针-1。但是,我们会发现一个问题,如上面的第四个图,0,1,2三个间并没有使用。因此,为了占用该间,我们使用了循环队列来实现。 循环队列原理图: 我们可以发现,当循环队列属于上图的d1情况时,是无法判断当前状态是还是。为了
循环队列的条件
woxiaozhi的专栏
05-23 2161
为了方便起见,约定:初始化建时,令       front=rear=0,   当时:front=rear   当时:front=rear 亦成立   因此只凭等式front=rear无法判断还是。  有两种方法处理上述问题:     (1)另设一个标志位以区别队列还是。     (2)少用一个元素间,约定以“队列头指针front在尾指针rear的下一个位
(图解)循环队列的三种判断操作(附带源码和插入删除操作等一些基本操作)
在夜里行走的博客
10-15 2万+
一万字图解循环队列附带测试程序的源码
python数据结构算法详解与源码
08-20
数据结构算法(Python) 一、引入概念 1-01算法引入 1-02 时间复杂度与大O表示法 1-03-最坏时间复杂度与计算规则 1-04-常见时间复杂度与大小关系 1-05-代码执行时间测量模块 1-06-Python列表类型不同操作的...
数据结构算法与应用-C__语言描述
01-19
本书在简要回顾了基本的C++ 程序设计概念的基础上,全面系统地介绍了队列、堆、树、图等基本数据结构,以及贪婪算法、分而治之算法、分枝定界算法等多种算法设计方法,为数据结构算法的继续学习和研究奠定了一...
循环队列判断队列的3种方法
xxxxxxyao的博客
02-14 5万+
  一.少用一个存储位置   第一种情况: 当队列时条件:rear == front 当队列时条件为:rear+1 == front      上述方式对于上述图是适用的,但如果出现了有下标标识,上述判断条件就不适用了。比如下图有下标了,当队列时,显然条件就不能判断了,就要用到另一种判断。   第二种情况: 当队列时条件:rear == front 当队列时条件为:(rear+1)...
循环队列判断_计软考研双日练 | 如何判循环队列
weixin_39568781的博客
12-18 467
☝☝☝软件工程考研独家平台撰稿| 康康哥编辑| 丽丽姐本文由懂计算机、软件工程的博士师哥原创双日练:NO.20200922循环队列放在一维数组A[0…M-1]中,end1指向头元素,end2指向尾元素的后一个位置。假设队列两端均可进行入和出操作,队列中最多能容纳M-1个元素。初始时为。下列判断的条件中,正确的是 ( )。A.:end1 == end2;:...
循环队列判断_我所知道的数据结构队列
weixin_39732506的博客
12-18 1372
一、什么是消息队列官方定义:队列(quene)是允许在一端进行插入操作,而在另一端进行删除操作的线性表1.队列是一个有序列表,可以用 数组或是链表 来实现。2.遵循 先入先出 的原则。即:先存入队列的数据,要先取出。后存入的要后取出比如春运时的标语排走得了、走的及时、走得安全、走的舒适优先排的人, 优先处理. (买票, 结账, WC)队列的插入和删除对于来说,只需要一个顶指针就可以了。但是...
基础数据结构队列(queue)的学习与应用
ccnacyq的专栏
10-20 220
数据结构队列(queue) 什么是队列? 应用场景 图解原理 队列的操作接口 顺序队列代码实现 循环队列代码实现 什么是队列队列是一种“先进先出”(FIFO)的数据结构,是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。和一样,队列是一种操作受限制的线性表。进行插入操作的端称为尾,进行删除操作的端称为对头。队列中没有元素时,称为队列 应用场景 你有没有过电脑死机,或者游戏卡顿。用户点击是乎都没有用,就当你正要重启电脑或者杀掉游戏时。
循环队列的两种判断队列的条件
qq_44332021的博客
11-19 9140
少一个存储位置的 队列时:rear= =front 队列时:(rear+1)%maxSize= =front 不少一个存储位置时:加一个标志flag或者计数的count 入时flag=true 出时flag=false :rear= =front&flag :rear= =front&!flag 开始时count=0 入时:count++ 出是:count– :rear ==front &&count=maxsize :rear ==front
数据结构循环队列判断
最新发布
weixin_65244731的博客
10-21 2356
简单易懂----数据结构循环队列判断
循环队列判定
疯狂的1024
06-18 3万+
不同的情况判断的情况是不一样的。顺序存储结构的循环队列假设循环队列尾指针是rear,头是front,其中QueueSize为循环队列的最大长度。(1) 入尾指针前进1:(rear+1)%QueueSize(2) 出头指针前进1:(front+1)%QueueSize例1, 例2(3) 队列长度:(rear-front+QueueSize)%QueueSize例3:现有一...
如何判断循环队列or
qq_42006733的博客
02-16 1万+
什么是循环队列 循环队列就是将队列存储间的最后一个位置绕到第一个位置,首尾相连形成逻辑上的环状间,供队列循环使用。 循环队列可以更简单防止假溢出的发生,但队列大小是固定的。 假溢出 作为队列用的存储区还没有,但队列却发生了溢出,我们把这种现象称为"假溢出" 解决假溢出有两种方案: 一、将队列元素向前搬移。 二、将队列看成首尾相连,即循环队列。 如何判断循环队列or...
怎么判断循环队列是否为?或者已经了?
You_are_my_dream的博客
03-29 3万+
现有一个循环队列,其头指针为 front,尾指针为 rear,循环队列的总长度为 N,问怎么判断循环队列了? 正确答案: D    front==rear front==rear+1 front==rear%n front==(rear+1)%n 当队列不为时,front指向队列的第
队列顺序存储结构中的循环队列与判的过程
weixin_43596200的博客
10-16 2678
循环队列介绍 这里介绍的时队列的顺序存储结构: 初始时:Q.front = Q.rear = 0; 首指针进1:Q.front = (Q.front+1)%maxSize; 尾指针进1:Q.rear = (Q.rear +1)%maxSize; 队列长度: (Q.rear +maxSize-Q.front)%maxSize; 出时:指针都按顺时针方向进 1。 显然,的条件是:Q.front = Q.rear。但是,如果入的速度快于出的速度,尾指针很快就赶上首指针,此时,也有:Q.fr
循环队列的优点是什么?如何判断循环队列?
05-10
判断循环队列需要维护两个指针变量front和rear,分别表示头和尾的位置。当时,front和rear指向同一个位置;当时,尾的下一个位置是头,即(rear+1)%n=front,其中n表示循环队列的长度,%...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • 1.1.1.1校园网_突破校园网限制,开启寝室Wifi 22810
  • 设备能力指数cmk计算公式_简单速成!3分钟学会CMK、CPK、PPK工具! 12704
  • 2021宝应各高中高考成绩查询,2019扬州大市各高中高考情况如何,看超全喜报!... 9066
  • 一份完整的问卷模板_Word制作问卷调查模板表「教你复选框打钩」 5517
  • windows强制覆盖正在打开的文件_WIN10打开的文件夹窗口老在最前面,遮挡/覆盖住其它打开的窗口问题解决... 5154

您愿意向朋友推荐“博客详情页”吗?

  • 强烈不推荐
  • 不推荐
  • 一般般
  • 推荐
  • 强烈推荐
提交

最新文章

  • 新射雕英雄传服务器维护,37《新射雕英雄传》12月31日停止运营公告
  • 服务器缓存网站win,Windows DNS 服务器缓存时间及缓存服务器的配置
  • 跨域ajax原理,跨域 ajax 请求之 cors 原理解析
2021年152篇
2020年217篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

聚圣源委内瑞拉总统大学起名命运多舛的意思crossange天使与龙的轮舞监理公司起名大全国士无双最新章节五行缺水女孩怎么起名历史小说排行榜诗词起名软件有创意烟酒商行起名中国语言文字网新生儿起名责任公司君临九天深夜食堂分集剧情介绍在线起名字测试打分红色故事小学生猪年宝宝取名起名大全宜用字雄霸天下全集医嫁红楼梦好词好句周易免费测名网房子起个名字起名字大师免费下载军事小说网双环小贵族8月8日生人起名招商加盟网王府幼儿园国务委员名单虎年女宝宝起名宜用字淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男孩疑遭霸凌 家长讨说法被踢出群国产伟哥去年销售近13亿网友建议重庆地铁不准乘客携带菜筐雅江山火三名扑火人员牺牲系谣言代拍被何赛飞拿着魔杖追着打月嫂回应掌掴婴儿是在赶虫子山西高速一大巴发生事故 已致13死高中生被打伤下体休学 邯郸通报李梦为奥运任务婉拒WNBA邀请19岁小伙救下5人后溺亡 多方发声王树国3次鞠躬告别西交大师生单亲妈妈陷入热恋 14岁儿子报警315晚会后胖东来又人满为患了倪萍分享减重40斤方法王楚钦登顶三项第一今日春分两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?周杰伦一审败诉网易房客欠租失踪 房东直发愁男子持台球杆殴打2名女店员被抓男子被猫抓伤后确诊“猫抓病”“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火男孩8年未见母亲被告知被遗忘恒大被罚41.75亿到底怎么缴网友洛杉矶偶遇贾玲杨倩无缘巴黎奥运张立群任西安交通大学校长黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发妈妈回应孩子在校撞护栏坠楼考生莫言也上北大硕士复试名单了韩国首次吊销离岗医生执照奥巴马现身唐宁街 黑色着装引猜测沈阳一轿车冲入人行道致3死2伤阿根廷将发行1万与2万面值的纸币外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万手机成瘾是影响睡眠质量重要因素春分“立蛋”成功率更高?胖东来员工每周单休无小长假“开封王婆”爆火:促成四五十对专家建议不必谈骨泥色变浙江一高校内汽车冲撞行人 多人受伤许家印被限制高消费

聚圣源 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化