队列是一种“先进先出的数据结构”,可分为静态队列和链式队列。静态队列一般使用数组实现,数组需要预先定义内存大小,为了避免内存浪费,一般使用循环队列。著名的生产者与消费者理论,一个写数据,一个读数据,使得内存可以重复利用。接下来讲述循环队列的原理以及实现代码。
分析下面数组的实现过程,假设数组的大小为5
该方法存在一个问题: 当rear和front到数组下标最后一个元素后,再写入或读出该如何操作?——答案是我们将它抽象为环形
当tail为4的时候,实际上已经到数据5这个位置了,再写就会导致溢出,因此我们tail = (tail+1)%buf_size,结果为0,因此就回到了0。
空时条件front==tail,满时也为front==tail, 如何判断循环buffer是否为空或满?
解决办法:尾部更新 tail = (tail+1)%rb_size;
空一个存储单位不存储数据,这样:
-
空条件: rear==front
-
满条件: (rear+1) % rb_size == front
-
buffer中数据大小: (rear+rb_size-front)%rb_size
具体实现参考链接:队列的实现(1):循环队列的实现_(1)实现一个循环队列。向队列中插入自己名字对应的拼音(一个字母对应一个元素,),-CSDN博客
我是用了一个变量size来实时监测数组里元素的大小,用上面的方法把判断满还是空换掉就行。
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#define SIZE 8 // 缓冲区大小
typedef struct ring_buffer_s {
int head;
int tail;
int size;//(tail+SIZE-head)%SIZE
char buffer[SIZE];
}ring_buffer_t;
void ringbuffer_init(ring_buffer_t *rb);
int ringbuffer_read(ring_buffer_t *rb, int *data);
int ringbuffer_write(ring_buffer_t *rb, int data);
bool ringbuffer_empty(ring_buffer_t *rb);
bool ringbuffer_full(ring_buffer_t *rb);
void ringbuffer_print(ring_buffer_t *rb);
int main (int argc, char **argv)
{
ring_buffer_t rb;
int i;
int data;
ringbuffer_init(&rb);
for( i=0; i<SIZE; i++)
{
if( ringbuffer_write(&rb, i) == 1 )
{
printf("write %d success\n",i);
}
printf("buffer is full,cannot write %d\n",i);
}
ringbuffer_print(&rb);
for( i=0; i<5; i++)
{
if (ringbuffer_read(&rb, &data))
{
printf("Read %d from buffer\n", data);
}
else
printf("buffer is empty\n");
}
ringbuffer_print(&rb);
return 0;
}
void ringbuffer_init(ring_buffer_t *rb)
{
rb->head = 0;
rb->tail = 0;
rb->size = 0;
}
bool ringbuffer_full(ring_buffer_t *rb)
{
return rb->size == SIZE;
//(rb->tail+1)%SIZE == head;
}
bool ringbuffer_empty(ring_buffer_t *rb)
{
return rb->size == 0;
//tail == head
}
int ringbuffer_write(ring_buffer_t *rb, int data)
{
if(ringbuffer_full(rb))
{
return -1;
}
rb->buffer[rb->tail] = data;
rb->tail = (rb->tail+1)%SIZE;
rb->size++;
return 1;
}
int ringbuffer_read(ring_buffer_t *rb, int *data)
{
if( ringbuffer_empty(rb) )
return -1;
*data = rb->buffer[rb->head];
rb->head = (rb->head+1)%SIZE;
rb->size--;
return 1;
}
void ringbuffer_print(ring_buffer_t *rb)
{
int i = rb->head;
int count = rb->size;
while( count > 0 )
{
printf("%d",rb->buffer[i]);
i = (i+1)%SIZE;
count--;
}
printf("\n");
}