链式队列
链式栈:我们使用的是无头单向链表,无头单向链表的头为栈顶,对无头单向链表进行头插头删。
链式队列:我们使用的是有头单向链表,有头单向链表的头结点为队头,终端结点为队尾。对有头单向链表进行头删、尾插。
1.概念
队列的链式存储结构,其实就是线性表的单链表,只不过它是操作受限的线性表。它只能尾进头出而已,将其简称为链式队列。
为了操作上的方便,我们将队头指针指向链式队列的头结点,而队尾指针指向终端结点,如下图所示。
空队列时,front
和rear
都指向头结点,如下图所示:
接口实现
链式队列函数定义
初始化函数 | LQ *LQInit(); |
入队函数 | int LQInQueue(LQ *PQ, LQDataType data); |
出队函数(返回出队数据) | LQDataType LQOutQueue(LQ *PQ); |
计算长度函数(返回int类型长度) | int LQLength(LQ *PQ); |
打印(显示内容)函数 | void LQPrint(LQ PQ); |
清空函数 | void LQClear(LQ *PQ); |
创建空的链式队列
- 开辟空间存放操作链式队列的结构体
- 在给结构体成员(队头指针
front
和队尾指针rear
)进行初始化的时候开辟空间存放头结点
让队头指针front
和rear
同时指向这段空间。
3.对头结点进行初始化,让其指针域指向NULL
链式队列入列
LinkQueue.c文件(函数定义)
#include "LinkQueue.h"
LQ *LQInit()
{
LQ *PQ = (LQ *)malloc(sizeof(LQ));
if (NULL == PQ)
{
printf("LQInit failed, PQ malloc err.\n");
return NULL;
}
PQ->front = PQ->rear = (LL)malloc(sizeof(LLN));
if (NULL == PQ->front)
{
printf("LQInit failed, PQ->front or PQ->rear malloc err.\n");
return NULL;
}
PQ->front->next = NULL;
return PQ;
}
int LQInQueue(LQ *PQ, LQDataType data)
{
LL PNew = (LL)malloc(sizeof(LLN));
if (NULL == PNew)
{
printf("LQInQueue failed, PNew malloc err.\n");
return -1;
}
PNew->data = data;
PNew->next = NULL;
PQ->rear->next = PNew;
PQ->rear = PNew;
return 0;
}
LQDataType LQOutQueue(LQ *PQ)
{
if (PQ->front == PQ->rear)
{
printf("LQOutQueue failed, LQ is empty.\n");
return -1;
}
LL PDel = PQ->front;
PQ->front = PQ->front->next;
free(PDel);
PDel = NULL;
return PQ->front->data;
}
int LQLength(LQ PQ)
{
int len = 0;
if (PQ.front == PQ.rear)
{
return 0;
}
else
{
while (PQ.front->next)
{
len++;
PQ.front = PQ.front->next;
}
return len;
}
}
void LQPrint(LQ PQ)
{
if (PQ.front == PQ.rear)
printf("队列为空\n");
else
{
printf("队列为:");
while (PQ.front->next)
{
printf("%d ", PQ.front->next->data);
PQ.front = PQ.front->next;
}
putchar(10);
}
}
void LQClear(LQ *PQ)
{
while(PQ->front != PQ->rear)
LQOutQueue(PQ);
}
LinkQueue.h文件
头文件:存放函数声明
链式队列结构体定义(内含数据、头指针、尾指针)
头指针、尾指针的结构体定义(单链表结点)
内含数据域data和指针域next
#ifndef _LINKQUEUE_H_
#define _LINKQUEUE_H_
#include <stdio.h>
#include <stdlib.h>
typedef int LQDataType;
typedef struct LinkListNode
{
LQDataType data;
struct LinkListNode *next;
} LLN, *LL;
typedef struct LinkQueue
{
LL front;
LL rear;
} LQ;
LQ *LQInit();
int LQInQueue(LQ *PQ, LQDataType data);
LQDataType LQOutQueue(LQ *PQ);
int LQLength(LQ PQ);
void LQPrint(LQ PQ);
void LQClear(LQ *PQ);
#endif
test.c文件(主函数以及相关函数的调用)
#include "LinkQueue.h"
int main(int argc, char const *argv[])
{
LQ *PQ = LQInit();
LQInQueue(PQ, 10);
LQInQueue(PQ, 20);
LQInQueue(PQ, 30);
LQPrint(*PQ);
LQOutQueue(PQ);
// for (int i = 0; i < 3; i++)
// {
// int data = LQOutQueue(PQ);
// printf("出队数据是%d\n", data);
// }
printf("队列长度为%d\n", LQLength(*PQ));
LQPrint(*PQ);
LQClear(PQ);
printf("队列长度为%d\n", LQLength(*PQ));
free(PQ->front); //如果进行了LQClear操作,则只需要释放PQ->front或者PQ->rear,否则二者都需要释放
PQ->front = NULL;
free(PQ);
PQ = NULL;
return 0;
}
运行结果
makefile文件
CC=gcc
OBJS=test.o LinkQueue.o
CFLAGS=-c -g -Wall
test:$(OBJS)
$(CC) -o $@ $(OBJS)
%.o:%.c
$(CC) $(CFLAGS) $< -o $@
.PHONY:clean
clean:
$(RM) *.o test