学习线性表,高深又烧脑?莫怕,手把手教你终结烦恼!(队列:顺序存储结构(二))

上次我们提到,队列的顺序存储结构是完全可以优化的,从而避免不必要的空间上的浪费,今天,我们就来学习,并且实现一下。

解决这个问题的主要办法就是把队列的头和尾连接起来,成为一个环形的队列,我们称它为环形队列或循环队列。环形队列首尾相连后,当队尾指针rear==MaxSize-1后,再前进一个位置就到达0,于是就可以使用另一端的空位置存放队列元素了。实际上存储器的地址总是连续编号的,因此我们可以使用数学上的取余运算%来实现。

为此我们可以把原来的front或rear自增换成front=(front+1)%MaxSize;rear=(rear+1)%MaxSize;至于什么意思,你品,你细品......就有内味儿了吧。环形队列的队头指针front和队尾指针rear初始化时都置为0,即front=rear=0。在进队和出队时,队头指针和队尾指针分别循环增1。那么,环形队列的队空和队满如何设置呢?显然队空条件是rear==front。但是当进队的速度快于出队的速度时,队尾指针会追赶上队首的指针,此时看出环形队列的队满条件也是rear==front,这就产生了矛盾。那么怎样区分队空和队满呢?我们改为“队尾指针循环增1时等于队头指针”作为队满条件,也就是说尝试进队一次,若达到队头,就认为满了,不能再进队。这样循环队列少用一个元素的空间,即该队列中在任何时刻最多只能有MaxSize-1个元素。因此,在循环队列中设置队空的条件是rear==front;队满条件是(rear+1)%MaxSize==front。如下是循环队列的操作示意图:

在这样设计的循环队列中,我们可以使用如下方法实现循环队列:

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define MaxSize 50
typedef char ElemType;
typedef struct{
    ElemType data[MaxSize];
    int front,rear;//front指向队头,rear指向队尾。
}SqQueue;
void InitQueue(SqQueue* q){//初始化队列。
    q->front=q->rear=0;//设为初始状态,即front==rear==0。
}
void DestroyQueue(SqQueue* q){//销毁队列。
    free(q);//释放队列q占用的存储空间。
}
bool QueueEmpty(SqQueue* q){//判断队列是否为空。
    return q->front==q->rear;//队空条件:front==rear。
}
bool enQueue(SqQueue* q,ElemType e){//加入队列。
    if((q->rear+1)%MaxSize==q->front)return false;//若队列满了,则返回false。
    q->rear=(q->rear+1)%MaxSize;//队尾循环增1。
    q->data[q->rear]=e;//元素e插入队尾位置。
    return true;
}
bool deQueue(SqQueue* q,ElemType* e){//出队。
    if(q->front==q->rear)return false;//若队列为空,则返回false。
    q->front=(q->front+1)%MaxSize;//队头循环+1。
    *e=q->data[q->front];//取出队头元素。
    return true;
}

这样,我们就可以充分利用数组的空间,不用造成浪费了。循环队列到此结束,欢迎点赞,打赏,留言交流!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值