环形队列 C语言
队列是链表的变种,主要却别在于存储方式不同,队列是线性存储结构(支持索引访问,但不可随意增删节点),链表是链式存储结构(不支持随机访问,可随意增删节点)。
环形队列,使队列空间可以循环利用,访问速度和普通队列一致
下面时C语言实现代码:
/*
* 无边界的数据流环形队列缓冲区
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define min(x,y) ((x)<(y)?(x):(y))
typedef struct __queue {
unsigned char *buff; // 线性存储缓冲区
unsigned head; // 始终指向队列第一个元素位置
unsigned tail; // 始终指向最后一个元素位置的下一个位置, 初始队列头尾相等
unsigned size;
}QUEUE, *PQUEUE;
// 判断长度是否为2的次幂
bool is_power_of_2(unsigned n)
{
return ((n != 2) && ((n & (n-1)) == 0));
}
// 获取接近value的最大2的次幂
unsigned roundup_pow_of_two(unsigned value)
{
if(is_power_of_2(value))
{
return value;
}
short position = 0;
while(value != 0)
{
value >>= 1;
++position;
}
return (1 << position);
}
// 创建队列
PQUEUE create_queue( unsigned int size)
{
if(size < 1) return NULL;
size = roundup_pow_of_two(size);
PQUEUE pqueue = (PQUEUE)malloc(sizeof(QUEUE));
pqueue->buff = (char*)malloc(sizeof(unsigned char) * size);
if(NULL == pqueue->buff) return NULL;
pqueue->size = size;
pqueue->head = pqueue->tail = 0;
return pqueue;
}
unsigned queue_free(PQUEUE pqueue)
{
unsigned len = pqueue->size;
if(pqueue->head != pqueue->tail)
{
len = (pqueue->size - pqueue->tail + pqueue->head) & (pqueue->size - 1);
}
return len > 1 ? (len-1) : 0;
}
bool queue_empty(PQUEUE pqueue)
{
return (queue_free(pqueue) == pqueue->size);
}
bool queue_full(PQUEUE pqueue)
{
return (queue_free(pqueue) == 0);
}
void free_queue(PQUEUE pqueue)
{
if(NULL == pqueue) return;
if(pqueue->size > 0)
{
free(pqueue->buff);
}
free(pqueue);
}
// 插入数据
bool input_queue_data(PQUEUE pqueue, void* data, unsigned data_len)
{
if(NULL == pqueue) return false;
if(queue_full(pqueue)) return false;
unsigned free_len = queue_free(pqueue);
if(data_len > free_len)
{
return false;
}
if(pqueue->tail > pqueue->head)
{
unsigned len = pqueue->size - pqueue->tail;
if(len < data_len)
{
memcpy(pqueue->buff + pqueue->tail, data, len);
len = data_len - len;
memcpy(pqueue->buff, data, len);
pqueue->tail = len;
return true;
}
}
memcpy(pqueue->buff + pqueue->tail, data, data_len);
pqueue->tail += data_len;
return true;
}
// 取数据
unsigned output_queue_data(PQUEUE pqueue, void *data, unsigned data_len)
{
if(NULL == pqueue) return 0;
unsigned queue_buff_len = pqueue->size -1 - queue_free(pqueue);
data_len = min(data_len, queue_buff_len);
if((pqueue->head + data_len) <= pqueue->size)
{
memcpy(data, pqueue->buff, data_len);
} else {
unsigned len = pqueue->size - pqueue->head;
memcpy(data, pqueue->buff + pqueue->head, len);
data_len -= len;
memcpy(data+len, pqueue->buff, data_len);
}
pqueue->head = (pqueue->head + data_len) & (pqueue->size - 1);
return data_len;
}
int main( int argc, char *argv[] )
{
PQUEUE pqueue = create_queue(1024);
if(NULL == pqueue)
{
printf("创建队列失败!\n");
}
char data[] = "hello world";
unsigned len = strlen(data);
if(!input_queue_data(pqueue, data, len))
{
printf("插入失败!\n");
}
char buff[12] = {0};
output_queue_data(pqueue, buff, len);
printf("%s\n",data);
free_queue(pqueue);
return 0;
}

浙公网安备 33010602011771号