循环队列

问题描述:

   循环队列是一般队列的变种吧,就是将队列首尾相连了,貌似这样就不必考虑队列满而无法使用了,因为到了队列尾又会循环回到队列首。在嵌入式底层代码实现中,一些串行端口数据特别是串口,用到循环队列的情况还是蛮多的。

循环队列:

   将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。这个应当是比较成熟的定义了,简洁了当。像是一条蛇咬住自己的尾巴,而且蛇腔里面可以填充东西的感觉。

为什么用循环队列:

   主要是为了克服“假溢出”情况,系统作为队列用的存储区还没有满,但队列却发生了溢出,我们把这种现象称为"假溢出"。其实就是因为队列的first in first out特质所引起的,队列为获得first in first out特质,一般需要两个指针,一个称为“头指针”,一个称为“尾指针”,头指针用于在队列头部读出元素,尾指针用于在队列尾部插入新元素,先进去队列的元素位于队列的头部。对于使用顺序队列情况,随着队列尾部不断插入新元素,尾指针最终会指向分配给队列的最后的内存地址,当再有新元素要插入时,此时队列尾部已经无法插入新元素了。而头指针由于有元素出队列,队列内存空间的前面一部分其实还是空的,因此就造成了“假溢出”这种情况。循环队列就是为解决该问题的。(当然,解决假溢出还可以将队列元素做平移,但感觉使用循环队列会有更高的效率)。

用法

1. 队列置空:
void InitQueue(CirQueue *Q)
{
Q->front=Q->rear=0;
Q->count=0; //计数器置0
}
2. 队列判空:
int QueueEmpty(CirQueue *Q)
{
return Q->count==0; //队列无元素为空
}
3. 判断队列是否满:
int QueueFull(CirQueue *Q)
{
return Q->count==QueueSize; //队中元素个数等于QueueSize时队满
}
4. 元素队列尾部入队:
void EnQueue(CirQueue *Q,DataType x)
{
if(QueueFull(Q))
Error("Queue overflow"); //队满上溢
Q->count ++; //队列元素个数加1
Q->data[Q->rear]=x; //新元素插入队尾
Q->rear=(Q->rear+1)%QueueSize; //循环意义下将尾指针加1
}
5. 元素从队列头部出队列:
DataType DeQueue(CirQueue *Q)
{
DataType temp;
if(QueueEmpty(Q))
Error("Queue underflow"); //队空下溢
temp=Q->data[Q->front];
Q->count--; //队列元素个数减1
Q->front=(Q->front+1)%QueueSize; //循环意义下的头指针加1
return temp;
}

循环队列使用总结

优点是逻辑判断简单,执行程序实现容易。 缺点是执行时重复比较太多,效率不一定高,大型系统节点较多时不宜采用(重复比较太多的问题暂时未碰到,队列用来传递FIFO消息的情况较多,重复比较问题以后碰到再补充)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值