文章目录

循环队列的长度

队列:循环队列和双端队列/受限双端队列_取模运算

  • 我们设循环队列的长度(队列中存在的元素数量(实际有效长度))队列:循环队列和双端队列/受限双端队列_循环队列_02
  • 为了方便计算,我们为循环队列打了两重下标,第二重开始的下标是虚拟的
  • 第二重下标是第一重下标加上MaxSize后得到的(本例中MaxSize=8)
  • 并且,队列头指针F总是沿着顺时针的方向追赶队尾指针R
  • 我们允许R取得第二重下标,而F只允许取第一重下标中的值
  • 这样,队列的元素数量(实际长度)就可以表示为:
  • 队列:循环队列和双端队列/受限双端队列_数组_03
  • 而实际上,我们知道队列的元素长度队列:循环队列和双端队列/受限双端队列_取模运算_04是不会超过队列:循环队列和双端队列/受限双端队列_取模运算_05;
  • 恰好地,我们有一种运算(取模运算),队列:循环队列和双端队列/受限双端队列_算法_06
  • 队列:循环队列和双端队列/受限双端队列_算法_07
  • 为了同一表达式,我们限制R的值只可以在第二重下标中取得,并把此时的值记为(队列:循环队列和双端队列/受限双端队列_循环队列_08)
  • 队列:循环队列和双端队列/受限双端队列_算法_09

循环队列满/空判断

空判断

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

满判断

  • 判断队列满的方案有多种
  • 牺牲掉一个位置来判断​​队满​
  • 具体的判空条件为​​(Q.rear+1)%MaxSize==Q.front​
  • 之所以这里要用队列:循环队列和双端队列/受限双端队列_算法_10,队列:循环队列和双端队列/受限双端队列_数组_11
  • 这种情况下队列:循环队列和双端队列/受限双端队列_取模运算_12,这超过了数组下标的范围
  • 队列:循环队列和双端队列/受限双端队列_循环队列_13不可能超过数组的下标范围,这样及时满足队满条件,也无法做出正确判断!
  • 在队列的数据类型中设置​​size​​成员来表示队列元素个数
  • 或者设置​​tag​​​成员来区分​​Q.front==Q.rear​​是队满还是队空

循环队列入队

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

循环队列入队

  • ​front=(front+1)%MaxSize​

受限双端队列

双入单出

1

2

2

3

3

4

4

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

  • 共产生:队列:循环队列和双端队列/受限双端队列_循环队列_14中入队序列

2从左边入队

3从左侧入队
  1. 4321(4从左侧入队)
  2. 3214(4从右侧入队)
3从右侧入队
  1. 4213(4从左入队侧)
  2. 2134(4从右侧入队)

2从右边入队

3从左侧入队
  1. 43​​12​
  2. 3​​12​​4
3从右侧入队
  1. 4​​12​​3
  2. ​12​​34

小结:

  • 对于单出双端队列,其入队序列,一个鲜明的特点在于入队序列的(第一个入队的元素)​​起点​​是1(或者是第一个进入队列的元素)
  • 起点的两侧序列的元素序号各自从起点向外侧递增(类似于抛物线)

双出单入

  • 单入双处在进入序列是唯一的,但是在出队列上的可能性是很多的
  • 甚至于,当入队序列的长度n不超过3,即队列:循环队列和双端队列/受限双端队列_算法_15的时候,任意的出队列都有可能(覆盖n的全排列队列:循环队列和双端队列/受限双端队列_循环队列_16)
  • 而当队列长度达到4的时候(队列:循环队列和双端队列/受限双端队列_取模运算_17),那么会有一些出队列的序列是无法做到的,例如:
  • 42xx打头的出队序列就无法实现
  • 4213
  • 4231
  • 这是因为:
  • 最后一个入队列的元素4作为第一个出队元素,那么可以确定,4出队的时候,所有其他元素(1,2,3)都还在队列中
  • 导致2被加载1与3之间,无法在作为跟在4后面紧接着出列
  • 但是同时我们发现,41xx和43xx都是可以实现的出度序列