• 队列:循环队列和双端队列/受限双端队列


    循环队列的长度

    image-20220916092735070

    • 我们设循环队列的长度(队列中存在的元素数量(实际有效长度)) 为 L 为L L
    • 为了方便计算,我们为循环队列打了两重下标,第二重开始的下标是虚拟的
      • 第二重下标是第一重下标加上MaxSize后得到的(本例中MaxSize=8)
    • 并且,队列头指针F总是沿着顺时针的方向追赶队尾指针R
    • 我们允许R取得第二重下标,而F只允许取第一重下标中的值
      • 这样,队列的元素数量(实际长度)就可以表示为:
        • L ′ = R − F , 但是由于 R 可以取得第二重下标 , 因此 L ′ 可能是 L , 也可能是 L + M a x S i z e L'=R-F,但是由于R可以取得第二重下标,因此L'可能是L,也可能是L+MaxSize L=RF,但是由于R可以取得第二重下标,因此L可能是L,也可能是L+MaxSize
        • 而实际上,我们知道队列的元素长度 L L L是不会超过 M a x s i z e , 即 L ⩽ M a x s i z e Maxsize,即L \leqslant Maxsize Maxsize,LMaxsize;
        • 恰好地,我们有一种运算(取模运算), 可以使得 L + K × M a x S i z e → L 可以使得L+K\times MaxSize\to L 可以使得L+K×MaxSizeL
          • L = ( L + K × M a x S i z e ) % M a x S i z e L=(L+K\times MaxSize)\%MaxSize L=(L+K×MaxSize)%MaxSize
      • 为了同一表达式,我们限制R的值只可以在第二重下标中取得,并把此时的值记为( R ′ = R + M a x S i z e R'=R+MaxSize R=R+MaxSize)
        • 从而 L = ( R ′ − F ) % M a x S i z e = ( R + M a x S i z e − F ) 从而L=(R'-F)\%MaxSize=(R+MaxSize-F)%MaxSize 从而L=(RF)%MaxSize=(R+MaxSizeF)

    循环队列满/空判断

    空判断

    • 对于空队列,有Q.rear==Q.front

    满判断

    • 判断队列满的方案有多种
      • 牺牲掉一个位置来判断队满
        • 具体的判空条件为(Q.rear+1)%MaxSize==Q.front
          • 之所以这里要用 M a x S i z e MaxSize MaxSize, 是考虑到队满发生在 Q . r e a r = M a x S i z e − 1 是考虑到队满发生在Q.rear=MaxSize-1 是考虑到队满发生在Q.rear=MaxSize1
          • 这种情况下 Q . r e a r + 1 = M a x S i z e Q.rear+1=MaxSize Q.rear+1=MaxSize,这超过了数组下标的范围
          • 而 Q . f r o n t 而Q.front Q.front不可能超过数组的下标范围,这样及时满足队满条件,也无法做出正确判断!
      • 在队列的数据类型中设置size成员来表示队列元素个数
      • 或者设置tag成员来区分Q.front==Q.rear是队满还是队空

    循环队列入队

    • 假设rear指针指向
      • 队尾元素本身,或者
      • 队尾元素的下一个位置(空位)
    • 检查队列是否已满(上面两种rear的定义情况都可以用以下条件进行判满)
      • (Q.rear+1)%MaxSize==Q.front
    • 如果未满,则更新维护队尾指针rear=(rear+1)%MaxSize

    循环队列入队

    • front=(front+1)%MaxSize

    受限双端队列

    双入单出

    1
    22
    33
    44

    输入队列(按照左优先来组织(以1为中心))

    • 共产生: 1 × 2 3 = 8 1\times 2^3=8 1×23=8中入队序列
    2从左边入队
    3从左侧入队
    1. 4321(4从左侧入队)
    2. 3214(4从右侧入队)
    3从右侧入队
    1. 4213(4从左入队侧)
    2. 2134(4从右侧入队)
    2从右边入队
    3从左侧入队
    1. 4312
    2. 3124
    3从右侧入队
    1. 4123
    2. 1234
    小结:
    • 对于单出双端队列,其入队序列,一个鲜明的特点在于入队序列的(第一个入队的元素)起点是1(或者是第一个进入队列的元素)

    • 起点的两侧序列的元素序号各自从起点向外侧递增(类似于抛物线)

    双出单入

    • 单入双处在进入序列是唯一的,但是在出队列上的可能性是很多的
    • 甚至于,当入队序列的长度n不超过3,即 n ⩽ 3 n\leqslant 3 n3的时候,任意的出队列都有可能(覆盖n的全排列 A n n = n ! A_n^n=n! Ann=n!)
    • 而当队列长度达到4的时候( n > 3 n>3 n>3),那么会有一些出队列的序列是无法做到的,例如:
      • 42xx打头的出队序列就无法实现
        • 4213
        • 4231
        • 这是因为:
          • 最后一个入队列的元素4作为第一个出队元素,那么可以确定,4出队的时候,所有其他元素(1,2,3)都还在队列中
          • 导致2被加载1与3之间,无法在作为跟在4后面紧接着出列
          • 但是同时我们发现,41xx和43xx都是可以实现的出度序列
  • 相关阅读:
    抖音矩阵系统,抖音矩阵系统,抖音SEO源码。
    【PAT乙】2022秋季赛后总结
    《从菜鸟到大师之路 Nginx 篇》
    简述 HTML 的语义化标签是什么?
    密码学系列0-总述
    vue中封装el-table表格
    SpringMvc--CRUD
    【网络】想学TCP,这一篇就够了 —— TCP理论知识详解(基于前面手搓TCP服务端博客的补充)
    linux中执行.sh文件出现/bin/sh^M: bad interpreter: No such file or directory
    【论文解读系列】NER方向:LatticeLSTM (ACL2018)
  • 原文地址:https://blog.csdn.net/xuchaoxin1375/article/details/126906170