链式队列的数据结构特点是在队列的队头和队尾分别有指针front和指针rear,front指向队头,进行出队操作,rear指向队尾,进行入队操作,最前面有一个头节点,中间由数据节点构成。
队列的链式存储如下:
#include<stdio.h>
#include<malloc.h>
//数据节点
typedef struct QNode{
int data;
struct QNode* next;
}DataNode;
与单链表相似,每个队列的数据节点包括一个data值以及一个指向下一节点的指针next。
以及队列的头节点,包括队头指针front和队尾指针rear。
typedef struct {
DataNode* front;
DataNode* rear;
}HeadNode;
链队的初始化:
void InitQNode(HeadNode*& QN)
{
QN = (HeadNode*)malloc(sizeof(HeadNode));
QN->front = QN->rear = NULL;
}
构建一个空队列,只需开辟一个头节点的空间,装有指针front和指针rear,并将他们指向NULL。
链式队列的销毁:
void DestroyQNode(HeadNode*& QN)
{
DataNode* pre = QN->front, * p;
if (pre != NULL)
{
p = pre->next;
while (p != NULL)
{
free(pre);
pre = p;
p = pre->next;
}
free(pre);
}
free(QN);
}
从头节点开始,用双指针依次释放数据节点空间,直到剩下最后一个再退出循环,然后释放最后一个数据节点的空间,最后释放头节点空间。
判断是否为空:
bool EmptyQNode(HeadNode* QN)
{
return QN->front == NULL;
}
只需检查front或者rear是否为空指针。
数据进队操作:
void PushQN(HeadNode*& QN, int a)
{
DataNode* p = (DataNode*)malloc(sizeof(DataNode));
p->data = a;
p->next = NULL;
if (QN->rear == NULL)
{
QN->front = QN->rear = p;
}
else
{
QN->rear->next = p;
QN->rear = p;
}
}
先开辟一个数据节点空间,再判断这个队列是否为空。
如果为空,则将队首指针与队尾指针均指向该数据节点。
如果已有数据,则将该数据节点置于队尾,再将队尾指针指向该数据节点。
数据出队操作:
bool PullQN(HeadNode*& QN, int &a)
{
if (QN->rear == NULL)
{
return false;
}
DataNode* p = QN->front;
a = p->data;
if (QN->front == QN->rear && QN->front != NULL)
QN->front=QN->rear=NULL;
else
QN->front= p->next;
free(p);
return true;
}
如果队列本身是空的,则返回假。
否则如果队列只有这一个数据节点,则先将队首、队尾指针置空,再free()。
否则(有多个数据节点),则让队首指针指向要出队节点的后一个节点,再将其free()。
输出队列:
void DispQN(HeadNode* QN)
{
if (EmptyQNode(QN))
printf("空的\n");
else
{
DataNode* p = QN->front;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
}
最后在main()函数上实现:
int main()
{
HeadNode* QN;
InitQNode(QN);
if (EmptyQNode(QN))
printf("栈为空\n");
printf("\n元素进队\n");
for (int i = 0; i < 10; i++)
{
printf("在队尾插入元素%d:", i);
PushQN(QN, i);
DispQN(QN);
}
printf("\n元素出队\n");
for (int i = 0; i < 4; i++)
{
int value = 0;
PullQN(QN, value);
printf("从队头删除元素%d:", value);
DispQN(QN);
}
DestroyQNode(QN);
return 0;
}