开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情
- 今天简单写一个c语言的队列实现,首先来只吐舌猫做一个文章的开头。
实现方案
队列是一种先入后出的数据结构,head出队,从tail入队。
一般实现方案有两种,一般有数组,空间固定稳定,实现复杂;或者链表,实现简单,动态申请空间。
在实际使用中,动态空间如果频繁申请释放,效率是不太好的,如果逻辑有出现不释放的空间的可能性,那不出意外,代码在不久的将来肯定跑飞。所以本文仅实现基于数组的队列实现方案。
实现循环数组,出入对列移出数组时,返回数组开头处继续操作,就是把数组开头和结尾在逻辑上接在一起。
接口实现
front标识正要处理的索引对象,rear标识未保存数据的索引值。
入队
从front出队,rear入队,所以有节点的情况下,都是rear在前,front在后追赶。
入队一个对象,则rear加一。入队之前需要判断是否为满队列。
出队
出队操作,front索引值减一,效果如下图所示。出队之前需判断是否为空队列。
空状态
头尾指针 指向同一个索引值,代表队列为空。禁止出队操作,返回错误
满状态
可以看出来,rear追上front的位置了。这就是满队列的状态,需要禁止入队操作,返回错误。
最后一个空间不使用,这样可以把空状态和满状态区分起来,代码逻辑更简单一点,性价比更高。
代码示例
#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
typedef struct{
int cnt;
int front;
int rear;
void** dat;
}MYQUEUE,*MYQUEUEPtr;
static MYQUEUE MyQueue;
int queur_init(int Cnt)
{
int ArrCnt = Cnt+1;
MyQueue.cnt = ArrCnt;
MyQueue.front = MyQueue.rear = 0;
MyQueue.dat = (void**)malloc(ArrCnt*sizeof(void*));
memset(MyQueue.dat,0,ArrCnt*sizeof(void*));
return 1;
}
//return :1 is empty; 0 not empty
int queue_is_empty()
{
if(MyQueue.front == MyQueue.rear) return 1;
return 0;
}
//return :1 is full; 0 not full
int queue_is_full()
{
int Posi = MyQueue.cnt <= (MyQueue.rear + 1)?0:(MyQueue.rear+1);
if(MyQueue.front == Posi) return 1;
return 0;
}
//入队
// return: 1 入队失败;0 成功
int enqueue(void *dat)
{
if(queue_is_full() == 1){
return 1;
}
MyQueue.dat[MyQueue.rear] = dat;
MyQueue.rear = MyQueue.cnt <= (MyQueue.rear+1)?0:(MyQueue.rear+1);
return 0;
}
//出队
// return: NULL 出队失败
void* dequeue()
{
// printf("dequeue front[%d]MyQueue.rear[%d]\n",MyQueue.front,MyQueue.rear);
void* ret = NULL;
if(queue_is_empty() == 1) return ret;
// printf("dequeue [%d]\n",MyQueue.front);
ret = MyQueue.dat[MyQueue.front];
MyQueue.front = MyQueue.cnt <= (MyQueue.front + 1)?0:(MyQueue.front+1);
return ret;
}
int main(int argc, char** argv)
{
int * paraD = NULL;
int ArrCnt = 100;
queur_init(ArrCnt);
printf("this is empty? [%s]\n",queue_is_empty()==1?"yes":"no");
while(ArrCnt--){
paraD = (int*)malloc(4);
*paraD = ArrCnt;
enqueue(paraD);
}
printf("this is full? [%s]\n",queue_is_full()==1?"yes":"no");
ArrCnt = 100;
while(ArrCnt--){
paraD = (int*)dequeue();
if(paraD) printf("var [%d]\n",*paraD);
}
return 0;
}
加进去一个简单的接口测试,有兴趣的同学可以编译试试看,有问题联系我哈。
代码已经单独提出来接口,与代码无关。
使用一个全局变量,所以只能创建一个队列。
后续优化可以采用动态申请空间保存队列句柄,由接口申请并返回给应用保存,使用的时候一定再发回给接口。
这样就可以实例挺多实例。接口不是线程安全的,如果多线程使用,最好加一些锁,保持数据同步。