最近学习了用数组构成循环队列,总结如下:
顺序队列基本操作
0. 定义一个队列
1. 队列初始化
2. 判断队列是否为空
3. 判断队列是否满
4. 复位队列
5. 获得队列有效元素长度
6. 入队
7. 出队
8. 遍历
rear 是指向队尾元素的下一个,front是指向队头元素
0.定义一个队列
定义一个管理队列的结构体
typedef uint8_t queue_type;
typedef uint8_t size_type;
#ifndef NULL
#define NULL ((void *)0)
#endif
#define FULL_JUDGE
#define LIB_QUEUE_DEBUG
typedef struct{
queue_type * p_arr;
size_type front;//head
size_type rear; //tail
size_type size;
size_type valid_len;//
}queue_t;
1. 队列初始化
初始化获得一个队列
/*
* out------------------in
*<----a1,a2,a3,...,an <----
* ^ ^
* front rear
* head tail
*/
/*
ret 1 success 0 fail
*/
uint8_t lib_init_queue(queue_t * p_queue,queue_type * buf, size_type size)
{
if(buf == NULL)
return 0;
p_queue->p_arr = buf;
p_queue->valid_len = p_queue->front = p_queue->rear = 0;
p_queue->size = size;
return 1;
}
2. 判断队列是否为空
当头指针和尾指针相等是则是空队列
/*
ret 1 empty 0 not empty
*/
uint8_t lib_queue_is_empty(queue_t * p_queue)
{
if( (p_queue->front) == (p_queue->rear) )
return 1;
return 0;
}
3.判断队列是否满
当尾指针加一对队列容量取余后等于头指针则队列已满
/*
ret 1 full 0 not full
*/
uint8_t lib_queue_is_full(queue_t * p_queue)
{
if( ((p_queue->rear+1)%p_queue->size) == p_queue->front )
return 1;
return 0;
}
4.复位队列
void reset_queue(queue_t * p_queue)
{
p_queue->front = p_queue->rear = 0;
}
5.获得队列有效元素个数
/*
ret queue len
情况1:当rear大于front时,队列元素个数:rear - front
情况2:当rear小于front时,队列元素个数分为2部分,0+rear 和 size-front,将2部分个数和起来
为rear-front+size
综上2种情况,元素个数是(rear-front+size) % size
*/
size_type lib_get_queue_len(queue_t * p_queue)
{
//(tail - head + size)%size
p_queue->valid_len = (p_queue->rear - p_queue->front + p_queue->size)%p_queue->size;
return p_queue->valid_len;
}
6.入队
入队之前要判断队列是否是满的
/*
ret 1 sucess 0 fail
*/
uint8_t lib_en_queue(queue_t * p_queue,queue_type m)
{
#ifdef FULL_JUDGE // full judge
if(lib_queue_is_full(p_queue) == 1)
return 0;
#endif
p_queue->p_arr[(p_queue->rear)] = m; //add m to tail
p_queue->rear = (p_queue->rear + 1)%p_queue->size; //updete rear
return 1;
}
7.出队
出队之前要判断队列是否是已空
/*
ret 1 sucess 0 fail(empty)
*/
uint8_t lib_de_queue(queue_t * p_queue,queue_type * m)
{
if(lib_queue_is_empty(p_queue) == 1)
return 0;
if(m != NULL)
*m = p_queue->p_arr[p_queue->front]; //got *m
#ifdef LIB_QUEUE_DEBUG
p_queue->p_arr[p_queue->front] = 0;
#endif
p_queue->front = (p_queue->front + 1)%p_queue->size; //updete front
return 1;
}
8.遍历
下面是遍历队列里元素并求均值
/*
ret queue avg
*/
queue_type lib_avg_queue(queue_t * p_queue)
{
uint8_t i;
uint32_t sum=0;
if(lib_queue_is_empty(p_queue) == 1)
return 0;
i = p_queue->front;
while( i != p_queue->rear)
{
sum = sum + p_queue->p_arr[i];
i = (i+1)%p_queue->size;
}
return sum/lib_get_queue_len(p_queue);
}
应用例子
#define BTRXSIZE 128
void main()
{
uart_data_t btrx_fifo; //bt fifo manage struct
queue_type btrx_arr[BTRXSIZE]; //bt fifo arr
lib_init_queue(&btrx_fifo.fifo,btrx_arr,BTRXSIZE);//初始化
lib_en_queue(&btrx_fifo.fifo,USART_ReceiveData(USART1));//入队
lib_de_queue(&uart_data->fifo,NULL); //出队
}