概念
队列是模拟一组人排队办事行为的数组结构
。
队列的直观体验:https://www.cs.usfca.edu/~galles/visualization/QueueArray.html
顺序队列
队列采用顺序存储结构
时,可利用一维数组来存放节点数据,在数组中ucArray[]
中存放队列。
head与tail的引入
由于队列的操作只能在队头和队尾上
进行,且不能移动队列中的节点
,因此必须有活动的队头和队尾的索引。
图中ucHead
为头索引,指向一个满节点
;ucTail
为尾索引,指向一个空节点
。
用C语言描述
#define MAXSIZE (128) //队列的最大长度
typedef struct _queue_t_
{
unsigned char ucArray[MAXSIZE]; //所用的内存空间
unsigned char ucHead; //队头索引
unsigned char ucTail; //队尾索引
}queue_t;
出队时
ucHead ++;
入队时
ucArray[ucTail ++] = x;
不足:
当其入队到最后时,要做一次整体搬移动作,以腾出空间。
数据搬移用时会较长,影响入队速度。
而循环队列则不会出现此问题
循环队列(ring-buffer)
什么是循环队列
当ucTail=MAXSIZE-1
时,即已达到队列空间最末处时,再次入队时,ucTail=0
,重新指向队列空间的开始位置。
一般情况
队空
队满
如何判断队空队满
由上图的情况可以知道,ucHead与ucTail已经无法区分,故需要对现有标识物进行改造。
现在引入队列含有节点的个数icount
:
当队列为空时,icount=0
;
当队列为满时,icount=MAXSIZE
;
当入队时,icount++
;
当出队时,icount--
;
故循环队列的数据结构可以描述为:
#define MAXSIZE (128) //队列的最大长度
typedef struct _ring_queue_t_
{
unsigned char ucArray[MAXSIZE]; //所用的内存空间
unsigned char ucHead; //队头索引
unsigned char ucTail; //队尾索引
unsigned int iCount; //有效数据个数
}ring_queue_t;
其实,ucTail=ucHead+iCount
。但是会出现ucTail > MAXSIZE -1
的情况。故有ucTail=(ucHead+iCount)%MAXSIZE
为了减小数据结构占用的空间,可将上面的数据结构优化为:
#define MAXSIZE (128) //队列的最大长度
typedef struct _ring_queue_t_
{
unsigned char ucArray[MAXSIZE]; //所用的内存空间
unsigned char ucHead; //队头索引
unsigned int iCount; //有效数据个数
}ring_queue_t;
如何入队出队
入队
unsigned char ucTail = (ucHead + iCount) % MAXSIZE;
ucArray[ucTail] = x;
icount ++;
出队
ucHead++;
ucHead %= MAXSIZE
iCount --;
队列基本操作
1. 创建
2. 销毁
3. 入队
4. 出队
5. 清空队列
6. 判断队列为空
7. 判断队列为满
8. 获得队列长度
9. 读取队列某一位置的元素值
循环队列的接口与实现
https://gitee.com/hany_li/hany_gear_lib/tree/master/ring_buffer