目录
1.队列的概念及结构
2.队列的实现
2.1队列结构定义
2.2队列的初始化及销毁
2.3数据入队
2.4数据出队
2.5访问队头数据
2.6访问队尾数据
2.6判断队列是否为空
2.7求队列的大小
2.7打印队列
队列:只允许在一端进行插入数据操作,另一端进行删除数据操作的特殊线性表
队列中先进先出FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
队列结构可以使用数组和链表结构实现,但一般采用的是链表,因为对于数组结构,队头出数据的效率较低
使用链表实现队列,队列中的每个元素都是节点的形式,所以需要定义节点的结构
对于队列,其具有队尾入数据,队头出数据的特性,所以其结构定义需要两个指针,分别指向队头和队尾
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
初始化即队列为空队列,队头指针和队尾指针都指向空
销毁队列,即释放队列中所有节点的空间,队头指针和队尾指针重新指向空
//队列初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
}
//队列销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* del = cur;
cur = cur->next;
free(del);
}
pq->head = pq->tail = NULL;
}
队列结构中,数据入队从队尾入,需要考虑空队列和非空队列两种情况
1️⃣空队列:
空队列和非空队列不同的是空队列插入数据时需要更新队头指针
//数据入队
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
else
{
newnode->data = x;
newnode->next = NULL;
}
//空队列时插入
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
//非空队列时插入
else
{
pq->tail->next = newnode;//链接新元素
pq->tail = newnode;//更新队尾
}
}
队列结构中,数据出队从队头出,对于空队列,出队操作非法
出队操作后,需要更新队头指针,并释放已出队节点的空间
特殊情况:队列中只有一个节点
//数据出队
void QueuePop(Queue* pq)
{
assert(pq);
//空队列不能进行出队操作
assert(!QueueEmpty(pq));
//队列中只有一个元素
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* del = pq->head;
pq->head = pq->head->next;
free(del);
del = NULL;
}
}
队头数据的访问操作在队列为空时非法,所以需要先断言,非空链表才可以进行队头数据的访问操作,通过队头指针访问即可
//访问队头数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
队尾数据的访问操作在队列为空时非法,所以需要先断言,非空链表才可以进行队尾数据的访问操作,通过队尾指针访问即可
//访问队尾数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
队列为空则队头指针和队尾指针都指向空,可以使用if-else语句进行返回
也可以参考以下代码,直接返回pq->head == NULL && pq->tail == NULL,只有当pq->head和pq->tail同时为NULL是才返回真,即队列为空
Note:
判空函数的返回类型为bool,但是C语言标准中没有bool类型,所以需要我们自己定义
#define bool int
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
/*if (pq->tail == pq->head == NULL)
{
return true;
}
else
{
return false;
}*/
return pq->head == NULL && pq->tail == NULL;
}
求队列的大小,遍历统计节点个数并返回即可
//求队列的大小
int QueueSize(Queue* pq)
{
assert(pq);
int size = 0;
QNode* cur = pq->head;
while (cur)
{
size++;
cur = cur->next;
}
return size;
}
为了便于观察入队与出队操作,可以编写一个打印函数便于调试
//打印队列
void QueuePrint(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}