环形队列 C语言
队列是链表的变种,主要却别在于存储方式不同,队列是线性存储结构(支持索引访问,但不可随意增删节点),链表是链式存储结构(不支持随机访问,可随意增删节点)。
环形队列,使队列空间可以循环利用,访问速度和普通队列一致
下面时C语言实现代码:
/* * 无边界的数据流环形队列缓冲区 **/ #include#include #include #include #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; }