队列与栈不同,队列实行先进先出,正如现实中的排队一样,这里选择使用单链表来实现,因为队列的出只能在队头操作实现,入队只能在队尾实现。而这正好对应单链表中尾插和头删。
1:定义
typedef struct QueueNode
{
int data;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
队列节点与单链表一致,包含数据域和next指针域,这里还需要定义两个指向队列节点的指针,分别指向队头和队尾,既然是指向队列节点的指针,那么就得是QNode类型的。
2:初始化
void QueueInit(Queue* pq)
{
pq->head = pq->tail = NULL;
}
初始化传入的是Queue类型的地址,最初状态无队列节点,只需要将head与tail置空即可。这里可能会有疑惑,既然对链队列操作,为何传入Queue*而不是QNode*。QNode*是指向队列的指针没问题,但是如此做就需要我们单独再定义QNode*head和QNode*tail来指向链队列的头尾,这样虽然可以实现,但是定义过于麻烦,不如将这个head与tail指针都绑定在一个结构体中来实现,同时在这个结构体中,这两个指针仍然是指向链队列节点的,类型不变,仍然是QNode*head和QNode*tail,而且指针的作用之一就是可以通过这个指针(也就是该变量的地址)来对变量进行修改操作。而这里传入的是Queue*,也就是head和tail的地址,可直接通过pq这个Queue类型的指针对head和tail进行修改操作,而head和tail又是QNode类型的指针,它俩又可以直接对队列节点进行修改操作。
3:入队
void QueuePush(Queue* pq, int x)
{
QNode*newnode=(QNode*)malloc(sizeof(QNode));
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
入队首先先开辟新的队列节点并进行赋值操作。这里分为2种情况,第一种如果说无节点(head和tail都是空,代码中直接写一个是空就可以了,写两个都是空也行),那么就直接将新开辟的节点赋给head和tail即可。第二种则是正常有节点的情况,实现单链表的尾插即可。
4:出队
void QueuePop(Queue* pq)
{
if (pq->head->next == NULL)
pq->head = pq->tail = NULL;
else
{
QNode* cur = pq->head->next;
free(pq->head);
pq->head = cur;
}
}
出队的话也是2种情况,第一种是只有一个节点了,也就是head->next为空,此时直接将head和tail置空即可。第二种就是正常的多个节点,实现单链表的头删即可。这里可能有人会发出如果队列中根本就没有节点的疑问,其实在后面代码的打印输出时,是根据另一个要写的判断是否为空的函数才进行打印输出操作和出队列操作的,如果队列为空,那根本不会执行到出队列操作的。简而言之就是出队列是要以队列中不空为前提来实现的。
5:判断队列是否为空
bool QueueEmpty(Queue* pq)
{
return pq->head == NULL;
}
直接返回pq->head==NULL就可,如果确实为空,那么返回1,否则返回0.
6:返回队头元素
int QueueFront(Queue* pq)
{
if (pq->head)
return pq->head->data;
}
如果队头有元素,那么直接返回队头元素即可。
7:队伍元素个数
int QueueSize(Queue* pq)
{
QNode* cur = pq->head;
int size = 0;
while (cur)
{
size++;
cur = cur->next;
}
return size;
}
比较简单,实现如代码所示
8:销毁链队
void QueueDestory(Queue* pq)
{
QNode* cur = pq->head;
while (cur)
{
QNode* after = cur->next;
free(cur);
cur = after;
}
}
实现如代码所示
9:打印输出队列元素
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
如果队列不空,才会进行打印和出队操作
全代码如下:
#include<iostream>
using namespace std;
typedef struct QueueNode
{
int data;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
void QueueInit(Queue* pq)
{
pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, int x)
{
QNode*newnode=(QNode*)malloc(sizeof(QNode));
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)
{
if (pq->head->next == NULL)
pq->head = pq->tail = NULL;
else
{
QNode* cur = pq->head->next;
free(pq->head);
pq->head = cur;
}
}
int QueueFront(Queue* pq)
{
if (pq->head)
return pq->head->data;
}
bool QueueEmpty(Queue* pq)
{
return pq->head == NULL;
}
void QueueDestory(Queue* pq)
{
QNode* cur = pq->head;
while (cur)
{
QNode* after = cur->next;
free(cur);
cur = after;
}
}
int QueueSize(Queue* pq)
{
QNode* cur = pq->head;
int size = 0;
while (cur)
{
size++;
cur = cur->next;
}
return size;
}
int main()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePush(&q, 5);
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
QueueDestory(&q);
return 0;
}
输出结果如下图: