目录
前言
链式队列(Linked Queue)是一种基于链表实现的队列数据结构。在链式队列中,每个元素都由一个节点表示,每个节点包含两部分:数据部分和指向下一个节点的指针部分。队列的头部通过链表的头指针表示,队列的尾部通过链表的尾指针表示。链式队列示意图如下图所示
图1 链式队列示意图
链式队列相比顺序队列的优势在于可以动态地分配内存空间,不受固定容量的限制。当需要入队时,只需在链表尾部新增一个节点;当需要出队时,只需删除链表头部的节点。这种设计使得链式队列对于频繁的入队和出队操作更为高效。
需要注意的是,在使用链式队列时要注意处理好指针的连接与更新,以避免出现内存泄漏或指针错乱等问题,接下来我们就分模块实现一下,然后编写一个测试代码进行测试:
1. 头文件的实现
1.1 定义队列数据类型
typedef int datatype;
1.2 定义队列元素结构体
这里就是队列元素的定义,结构体内容包括数据和下一个元素的指针。
typedef struct node {
datatype data;
struct node *next;
}listnode ,*linklist;
1.3 定义队列结构体
这里就是队列结构体的定义,包括头节点、尾节点的指针。
typedef struct {
linklist front;
linklist rear;
}linkqueue;
1.4 定义相关函数
定义初始化、入队、出队等相关函数。
linkqueue *queue_create();
int enqueue(linkqueue* lq,datatype x);
datatype dequeue(linkqueue *lq);
int queue_empty(linkqueue *lq);
int queue_clear(linkqueue *lq);
linkqueue* queue_free(linkqueue *lq);
2. 源文件的实现
2.1 队列生成函数实现
开辟队列空间和一个队列元素空间,将队列的front和rear指向这一个元素,并队这个元素的数据进行赋值(赋值多少无所谓),将队列元素的指向置为NULL。
linkqueue *queue_create()
{
linkqueue *lq;
if((lq= (linkqueue*)malloc(sizeof(linkqueue))) == NULL){//开辟队列空间
printf("malloc linkqueue failed\n");
return NULL;
}
lq->front = lq->rear = (linklist)malloc(sizeof(listnode));//开辟队列元素空间
if(lq->front == NULL)
{
printf("malloc node failed\n");
}
lq->front->data = 0;//进行队列front的初始化
lq->front->next = NULL;
return lq;
}
2.2 入队函数实现
链式队列入队如图所示
图2 入队示意图
需要注意的就是将队列的rear指向新生成的队列元素,下面进行队列入队函数的实现 。
int enqueue(linkqueue* lq,datatype x)
{
if(lq == NULL){//判断队列是否为空
printf("malloc linkqueue failed\n");
return -1;
}
linklist p = (linklist)malloc(sizeof(listnode));//开辟队列元素空间
if(p ==NULL)
{
printf("malloc node failed\n");
return -1;
}
p->data = x;//定义待入队元素的数值
p->next = NULL;//定义待入队元素的下一个指向位置默认为NULL
lq->rear->next = p;//入队
lq->rear = p;
return 0;
}
2.3 出队函数实现
链式队列出队如图所示
图3 出队示意图
这里我们做一个出队技巧,不需要操作队尾指针,直接将队列的第一个元素当作队头。
进行队列出队函数的实现
datatype dequeue(linkqueue *lq)
{
if(lq == NULL){//判断队列指针是否为空
printf("malloc linkqueue failed\n");
return -1;
}
linklist p;
p = lq->front;//出队技巧,不需要操作队尾指针,将队列的第一个元素当作队头
lq->front = p->next;
free(p);
p = NULL;
return (lq->front->data);
}
2.4 空队判断实现
进行队列是否为空的判断实现
图4 空队示意图
若队头指针等于队尾指针,则为空
int queue_empty(linkqueue *lq)
{
if(lq == NULL){//判断队列指针是否为空
printf("malloc linkqueue failed\n");
return -1;
}
return (lq->front == lq->rear ? 1 : 0);//若队头指针等于队尾指针,则为空
}
2.5 清空队列实现
当队列的头元素指向的第一个的元素存在时,就clear,这里也是用的出队技巧
int queue_clear(linkqueue *lq)
{
if(lq == NULL){//判断队列指针是否为空
printf("malloc linkqueue failed\n");
return -1;
}
linklist p;
while(lq->front->next)//当队列的头元素指向的第一个的元素存在时,就clear,这里也是用的出队技巧
{
p = lq->front;
lq->front = p->next;
printf("clear:%d\n",p->data);
free(p);
p = NULL;
}
}
2.6 释放队列实现
linkqueue* queue_free(linkqueue *lq)
{
if(lq == NULL){//判断队列指针是否为空
printf("malloc linkqueue failed\n");
return NULL;
}
linklist p;
while(lq->front)//这里释放掉全部的队列元素,包括头元素
{
p = lq->front;
lq->front = p->next;
printf("free:%d\n",p->data);
free(p);
}
free(lq);//释放队列
lq = NULL;
return NULL;
}
3. 代码测试
上面我们已经完成了队列的实现了,接下来我们编写一个测试代码进行功能测试。我们要实现的功能为:输入数字入队,输入字符出队。下面是我的test.c代码展示:
#include <stdio.h>
#include <stdlib.h>
#include "linkqueue.h"
int main(int argc,const char *argv[])
{
linkqueue *lq;
lq = queue_create();
if(lq==NULL)
return -1;
char input[10];
printf("please Num or Char\n");
while(1)
{
scanf("%s",input);
if(input[0]>='0'&&input[0]<='9')
{
enqueue(lq,atoi(input));
}
else
{
if(!queue_empty(lq))
{
printf("dequeue:%d\n",dequeue(lq));
}
}
}
return 0;
}
代码测试结果如下,成功!!!