[循环队列]使用原因与注意事项

原创 2015年07月11日 00:24:32
    问题描述:循环队列是一般队列的变种吧,就是将队列首尾相连了,貌似这样就不必考虑队列满而无法使用了,因为到了队列尾又会循环回到队列首。在嵌入式底层代码实现中,一些串行端口数据特别是串口,用到循环队列的情况还是蛮多的。当然,这只是一种数据结构,用在哪里都得看具体用途和是否能带来好处。为了更深一步的对这一结构的了解,进行了下整理和学习。
    循环队列:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。这个应当是比较成熟的定义了,简洁了当。像是一条蛇咬住自己的尾巴,而且蛇腔里面可以填充东西的感觉。
    为什么用循环队列:主要是为了克服“假溢出”情况,系统作为队列用的存储区还没有满,但队列却发生了溢出,我们把这种现象称为"假溢出"。其实就是因为队列的first in first out特质所引起的,队列为获得first in first out特质,一般需要两个指针,一个称为“头指针”,一个称为“尾指针”,头指针用于在队列头部读出元素尾指针用于在队列尾部插入新元素,先进去队列的元素位于队列的头部。对于使用顺序队列情况,随着队列尾部不断插入新元素,尾指针最终会指向分配给队列的最后的内存地址,当再有新元素要插入时,此时队列尾部已经无法插入新元素了。而头指针由于有元素出队列,队列内存空间的前面一部分其实还是空的,因此就造成了“假溢出”这种情况。循环队列就是为解决该问题的。(当然,解决假溢出还可以将队列元素做平移,但感觉使用循环队列会有更高的效率)。
    循环队列弊端:循环队列空和满时都是头指针等于尾指针,因此对于队列空和满的判断需要在代码中加以区别,有三种方式:一是另设一布尔变量来区别队列的空和满。二是少用一个元素的空间,每次入队前测试入队后头尾指针是否会重合,如果会重合就认为队列已满。三是设置一计数器记录队列中元素总数,不仅可判别空或满,还可以得到队列中元素的个数。
    循环队列类型定义:
#define QueueSize 100 //应根据具体情况定义该值
typedef char DataType; //DataType的类型依赖于具体的应用
typedef struct{
int front; //头指针,队非空时指向队头元素
int rear; //尾指针,队非空时指向队尾元素的下一位置
int count;//计数器,记录队中元素总数
DataType data[QueueSize];
}CirQueue;
    循环队列的基本运算:
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消息的情况较多,重复比较问题以后碰到再补充)。
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

使用Objective-C中foreach循环的一大注意事项

原文地址:http://blog.csdn.net/cheng_tian/article/details/5797411     前两天忙于做老师布置的新任务——制作一款iPhone上的“雷电”,做...

javascript中关键字in以及循环for...in的使用和注意事项

写这篇文章,是因为在学习prototypejs库中方法Object.extend()和Class.create(),看这篇指导[tutorial on classes and inheritance]...

开发报表-页面响应时间过长-for循环语句注意事项

package com.jd.sns.chat.common.manager.empdailyreport.impl; import java.text.DecimalFormat; import ...

Python学习笔记-Python的字符串,格式化,条件判断,循环、raw_input的注意事项

因为Python的诞生比Unicode标准发布的时间还要早,所以最早的Python只支持ASCII编码,普通的字符串'ABC'在Python内部都是ASCII编码的。Python提供了ord()和ch...

node.js在遇到“循环+异步”时的注意事项

nodejs的特征nodejs的最大特征就是一切都是基于事件的,从而导致一切都是异步的。nodejs的速度为什么快,其原理和nginx一样,他们都是通过事件回调来处理请求的,从而导致了整个处理过程中,...

Linux 进程间通信之消息队列的几点注意事项

1. 由于消息队列是属于内核的,因此在执行时,必须有Root权限才可以,否则会在访问消息队列时,出现EACCES错误,即访问权限的问题 2. msgbuf.mtype的设置 int msgsnd(...

分割器使用注意事项

  • 2014-05-22 20:56
  • 31KB
  • 下载

Android中的PendingIntent使用注意事项

在Android开发中,PendingIntent主要用于Notification、AlarmManager以及Widget中,获取PendingIntent主要有三种方式:getActivity()...

多重背景使用注意事项

  • 2014-12-17 17:12
  • 98KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)