C语言实现队列
1.队列的概念及结构
1.队列:只允许在一端进行插入数据操作,在另一端进行删除数据的特殊线性表,队列具有先进先出FIFO(First In First Out)入队列:进行插入操作的另一端称为队尾出队列:进行删除操作的一段被称为队头。
2.队列的结构:
因为我们用链表实现所以我们需要先构建一个节点的结构
Typedef struct QueueNode
{
struct QueueNode* next;
QDataType val;
}Qnode;
不过我们这里还需要再定义一个结构体,因为我们需要队头出数据和队尾如数据,对于单链表来说,从后一个数据找到前一个数据是很困难的,所以我们这里定义两个指针,一个指针指向头节点,一个指针,指向尾节点,这样方便我们插入数据和删除数据。
Typedef struct Queue
{
Qnode* phead;
Qnode* ptail;
int size
}
我们在这里定义了这个结构体不仅可以记录两个指针,还可以记录size为后面的操作带来便利,同时可以解决传二级指针的问题。
2.队列的实现
队列是可以使用数组的链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组上出数组效率较低,因为每次出一个数据,数组所有数据都需要向前挪动一位。
ok~,开始队列的实现:
头文件的代码如下:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType val;
}Qnode;
typedef struct Queue
{
Qnode* phead;
Qnode* ptail;
int size;
}Queue;
// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);
接下来我们一一实现
首先就是我们的队列初始化
void QueueInit(Queue* q)
{
assert(q); //断言
q->phead = NULL; //置空
q->ptail = NULL;
q->size = 0;
}
队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q); //断言
Qnode* newnode = (Qnode*)malloc(sizeof(Qnode)); //创建节点
if (newnode == NULL)
{ //创建失败退出
perror("malloc fail");
exit(1);
}
newnode->next = NULL; // 创建好了之后对新的节点初始化
newnode->val = data;
//插入队列时要分两种情况 1、队列中没有数据 2、队列中已经存在数据
if (q->ptail==NULL)
{ //当没有数据时 头尾指针同时指向 新节点
q->phead = q->ptail = newnode;
}
else
{ //当有数据时将创建好的新节点跟原来的尾节点链接
q->ptail->next = newnode;
q->ptail = newnode;
}
q->size++; //size++ 为后面做准备
}
队头出队列
void QueuePop(Queue* q)
{
assert(q); //断言一下
assert(q->size != 0); //既然我们要出数据所以我们这里的size不能为0,为0就是没有数据
//出队列同样分为两种情况 1、队列中只剩下一个数据 2、队列中存在多个数据
if (q->phead->next==NULL)
{ //队列中只存在一个数据时,释放完空间后将指针置为空
free(q->ptail);
q->phead = q->ptail = NULL;
}
else
{
//有多个数据时,需要将原来指向头结点的指针记录下来,删除之后,指向队列新的头节点
Qnode* cur = q->phead->next;
free(q->phead);
q->phead = cur;
}
q->size--;//每删除一个数据就size--
}
后面的就简单啦~
获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q); //断言
assert(q->phead); //获取头元素所以phead指针不能为空
return q->phead->val; //得到不为空后,直接返回phead指向的值
}
获取队列尾部元素(和头部元素同理)
QDataType QueueBack(Queue* q)
{
assert(q);
assert(q->ptail);
return q->ptail->val;
}
获取队列中有效地元素个数
这个时候我们刚刚记录的size的作用就来啦
int QueueSize(Queue* q)
{
assert(q);
return q->size; //直接返回size 即可
}
判断队列是否为空,为空返回true,反之返回false
bool QueueEmpty(Queue* q)
{
assert(q);
return q->size == 0;
}
队列的销毁
void QueueDestroy(Queue* q)
{
assert(q);
Qnode* cur = q->phead; //存下头节点
while (cur)
{
Qnode* next = cur->next; //一个个节点释放
free(cur);
cur = next;
}
q->phead = q->ptail = NULL;//最后置为空
q->size = 0;
}
这样我们的队列实现 就大功告成啦~感谢观看,如果对C语言数据结构感兴趣,关注巨可爱熊一起学习!