队列
我们已经知道,栈是一种后进先出的顺序表,二队列是一种先进先出的顺序表,就像我们日常生活中排队结账,排队上公交车,先到先享受一样,那么在c语言中,队列与栈一样,都可以用顺序表和链表实现,之前栈使用顺序表来实现的,比较好操作,但是队列就不一样,你要记录队头元素,以及队尾元素,就需要两个指针来记录,所以我们采用链表来实现队列。
队列的基本操作有以下接口
typedef int type //可自行定义队列中每个结点的数据类型
typedef struct qnode //队列结点的创建
{
struct qnode* next;
type data;
}qnode;
typedef struct queue //队头,队尾指针的创建以及队列大小
{
qnode* front;//头指针
qnode* rear;//尾指针
size_t size; //大小没有负
}queue;
void queueinit(queue* q); //队列的初始化
qnode* creatnode(type data); //结点创建
void queuepush(queue* q,type data); //入队
void queuepop(queue* q); //出队
type queuefront(queue* q); //获取对头元素
type queueback(queue* q); //获取队尾元素
size_t queuesize(queue* q); //当前队列大小
int queueempty(queue* q); //判断队列是否为空
void queuedestory(queue* q); //队列的销毁
接下来就一个接口一个接口的看吧
初始化
在这个接口中,需要对队列的头尾指针以及大小进行初始化,代码较简单,如下
void queueinit(queue* q)
{
q-front = q->rear = NULL; //头尾指针赋空
q->size = 0; //当前初始化大小为0
}
队列结点创建
创建节点后,要注意防止野指针出现,该接口也较为简单,代码如下
qnode* creatnode(type data)
{
qnode* node = (qnode*)malloc(sizeof(type)); // 通过动态内存申请空间
node->next = NULL; //next指针赋空
node->data = data;//结点数据赋值
return node;//返回这个创建的结点
}
入队
入队操作需要注意,要改变尾指针的指向,并且队列的size要增加1,与链表的尾插较为相似,具体接口代码如下
void queuepush(queue* q,type data)
{
if(q==NULL)
return ;//若队列不存在,直接返回空
qnode* node = creatnode(data);
if(q->front==NULL) //判断队列是否有首元素
q->front = q->rear = node; //头尾指向第一个结点
else{
q->rear->next = node; //尾结点指向下一个结点
q->rear = node; //尾指针改变
}
q->size++; //队列大小加1
}
出队
出队的时候,需要注意的是队列是否为空,如果为空,则表示出队失败,否则出队成功,出队后,当前的size需要减1。具体代码如下
void queuepop(queue* q)
{
if(q->front) //判断当前队列不为空
{
qnode* tmp = q->front; //临时结点方便释放
free(q->front); //释放头节点
q-front = tmp->next; //头指针指向下一个结点
if(q->front==NULL) //如果删除的是最后一个结点
q->rear = NULL; //尾指针置空
q->size--; //队列大小减1
}
}
获取队头元素
返回队头元素数据
type queuefront(queue* q)
{
if(q->freon)
return q->front->data;
}
获取队尾元素
返回队尾元素数据
type queueback(queue* q)
{
if(q->rear)
return q->rear->data;
}
获取当前队列大小
返回当前队列大小
size_t queuesize(queue* q)
{
return q->size;
}
判断队列是否为空
通过头指针或size大小判断
int queueempty(queue* q)
{
if(q->front==NULL)
return 1; //空则返回1
return 0;//非空返回0
}
销毁队列
这里和链表的销毁差不多,值得注意的是需要将头尾指针置空以及size置0,
void queuedestory(queue* q)
{
qnode* tmp = q->front; //获取队头以方便遍历释放
while(tmp)
{
qnode* p = tmp->next; //记录下一个需要释放结点
free(tmp); //释放当前结点
tmp = q; //找到下一个结点
}
q->front = q->rear = NULL; //头尾指针赋空
q->size = 0; //队列大小置0
}
总结
队列的实现在这里用的是链式结构,当然也可以通过顺序表来实现,循环队列的实现通常就是用顺序表来实现,下次我会写出循环队列的实现,方便大家参考。