c++输出双向队列的全部元素_数据结构——队列

  • Post author:
  • Post category:其他


0860cbe73b84222d7bca30fee220c017.png


初学者的每日学习笔记 2020.12.2

队列

队列的定义


为什么要用队列:

你们在用电脑时有没有经历,机器有时会处于疑似死机的状态,鼠标点什么似乎都没用,双击任何快捷方式都不动弹。就当你失去耐心,打算rest时。突然他像酒醒了一样,把你刚才点击的所有操作全部按顺序执行一遍。这其实是因为操作系统中的多个程序因需要通过一个通道输出,而按先后次序排队等待造成的。

再比如向移动、联通、电信等客服电话,客服人员与客户相比总是少数,在所有的客服人员都占线的情况下,客户会被要求等待,直到有某个客户人员空下来,才能让最先等待的客户接通电话。这里也是将所有当前打客服电话的客户进行排队处理。

操作系统和客服系统中,都是应用了一种数据结构来实现刚才提到的先进先出的排队功能,这就是队列。


队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。


队列是一种先进先出(First in First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。

假设队列是q=(a1,a2,…,an),那么a1就是队头元素,而an是队尾元素。这样我们就可以删除时,总是从a1开始,而插入时,列在最后。这也比较符合我们通常生活中的习惯,排在第一个的优先出列,最后来的当然在队伍的最后。

55e676f4d0a1499158cdae3b313c2954.png

队列在设计程序中用的非常频繁。比如用键盘进行各种字母或数字的输入,到显示器如记事本软件上的输出,其实就是对列的典型应用,假如你本来和女友聊天,想表达你是我的上帝,输入的是god,而屏幕上却显示出了dog发了出去,这真是要气死人了。

队列的概念:



栈和队列


是一对好兄弟,前面我们介绍过

数据结构与算法—栈详解

,那么栈的机制相对简单,后入先出,就像进入一个狭小的山洞,山洞只有一个出口,只能后进先出(在外面的先出去)。而队列就好比是一个隧道,后面的人跟着前面走,前面人先出去(先入先出)。日常的


排队


就是队列运转形式的一个描述!

所以队列的


核心理念


就是:先进先出!


队列的概念:

队列是一种特殊的

线性表

,特殊之处在于它只允许在表的

前端(front)

进行删除操作,而在表的

后端(rear)

进行插入操作,和栈一样,队列是一种

操作受限制

的线性表。进行插入操作的端称为

队尾

,进行删除操作的端称为

队头


队头front:

删除数据的一端。对于数组,

从后面插入更容易,前面插入较困难

,所以一般用数组实现的队列队头在前面。(删除,直接index游标前进,不超过队尾即可)。而对于链表。插入删除在

两头分别进行

那么

头部(前面)删除尾部插入

是最方便的选择。


队尾rear:

插入数据的一端,同上,在数组和链表中

通常均在尾部位置

。当然,其实数组和链表的front和rear还有点小区别,后面会具体介绍。

enQueue(入队):在

队尾

rear插入元素

deQueue(出队):在

对头

front删除元素


普通队列

按照上述的介绍,我们很容易知道数组实现的方式。用

数组模拟

表示队列。要考虑初始化,插入,问题。

080584ffd386973f0b26e4a4b20109e2.png
  • 初始化:数组的front和rear都指向0.
  • 入队:

    队不满



    数组不越界

    ,先队尾位置传值,再队尾下标+1
  • 出队:队不空,先取队头位置元素,在队头+1,

但是很容易发现问题,

每个空间域只能利用一次

。造成

空间

极度

浪费

。并且非常容易

越界

835f627fd32f89f0472ff29a5e20d380.png


循环队列

针对上述的问题。有个较好的解决方法!就是对已经申请的(数组)内存

重复利用

。这就是我们所说的循环队列。

而数组实现的循环队列就是在

逻辑上

稍作修改。我们

假设

(约定)数组的最后一位的下一个index是首位。因为我们队列中只需要front和tail两个指标。不需要数组的实际地址位置相关数据。和它无关。所以我们就只需要考虑尾部的特殊操作即可。

  • 初始化:数组的front和rear都指向0.
  • 入队:



    不满,先队尾位置传值,再

    rear=(rear + 1) % maxsize;
  • 出队:队不空,先取队头位置元素,

    front=(front + 1)%maxsize;
  • 是否为空:

    return rear == front;
  • 大小:

    return (rear+maxsize-front)%maxsize;

这里面有几个大家需要注意的,就是指标相加如果遇到最后需要转到头的话。可以判断是否到数组末尾位置。也可以直接+1求余。其中

maxsize

是数组实际大小。

b74e25f0ec649aee6ea5848a0b80da03.png


一、 队列的实现 Python

队列的定义:

def __init__(self,size = 100):
    self.queue = [0 for _ in range(size)] #限定队列的大小
    self.rear = 0  #队尾
    self.front = 0 #队首
    self.size = size


1.1 入队操作

算法:

步骤一:判断是否溢出,若溢出给出提示结束程序,否则跳到步骤二

步骤二:输入入队的元素

步骤三:将元素存于队尾处

步骤四:队尾下标自增

//入队操作

def push(self,element):
    if not self.is_filled():
        self.rear = (self.rear + 1) % self.size
        self.queue[self.rear] = element
    else:
        raise IndexError("Queue is filled")


1.2 出队操作

算法:

步骤一:判断是有元素,若无元素则给出提示结束程序,否则跳到步骤二

步骤二:用e接收出队的元素

步骤三:

步骤四:队尾下标自增

//出队操作

def pop(self):
    if not self.is_empty():
        self.front = (self.front + 1) % self.size
        return self.queue[self.front]
    else:
        raise IndexError("Queue is empty.")


1.3 判断队空

rear == front

def is_empty(self):
    return self.rear == self.front


1.4判断队满

(rear+1)%size == front

def is_filled(self):
    return (self.rear+1)%self.size == self.front


二、 Python中的内置队列模块

这里有个很容易搞混的:

import queue 只是为了保证线程安全

真正的队列模块是:

from collections import deque

它内部是一个双向队列。

from collections import deque
q = deque([1,2,3,4,5],5)  #后面的5限制队列的大小,如果队满,就自动把队首的出去
q.append() #从队尾进队,即右边进队
q.popleft() #从队首出队,即左边出队
#前面这属于单向队列


q.appendleft() #从队首进队,即左边进队
q.pop()   #从队尾出队,即右边出队

引用和参考:

数据结构-队列 – Timcode – 博客园​www.cnblogs.com

ac109e0b7e10ed0438305da46bfe3726.png

数据结构与算法-队列图文详解 – bigsai – 博客园​www.cnblogs.com

cd9833166dfa0b0efdecb6fbdb14b517.png



版权声明:本文为weixin_42126274原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。