1.一种特殊的线性表,只允许在一段进行插入,另一段进行删除;
2.进行插入操作的一端称为队尾,进行删除操作的一端称为队头;
3.队列具有先进先出的特性 FIFO(First In First Out)
队列总体来说是现实生活中的排队取号类似,先取票的,就先办理业务;队列中,先进入的,就先出去
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列类似顺序表头删数据,效率会比较低;此处我们就以链表结构实现队列举例:
1)结构定义:队列中我们在对头位置处队,对尾位置入队。为了便于操作,我们新建的一个结构体,用于存放队头、对尾位置的地址以及队中的数据个数。
typedef struct QueueNode {
QNDataType val;//数据域
struct QueueNode* next;//指针域
}QN;
typedef struct Queue {
QN* head;//头
QN* tail;//尾
int size;//有效数据个数,便于统计个数
}Queue;
2)初始化
// 初始化队列
void QueueInit(Queue* q) {
assert(q);
//初始队中无元素,队头、队尾都置为NULL
q->head = q->tail = NULL;
q->size = 0;
}
3)入队
// 入队
void QueuePush(Queue* q, QNDataType data) {
assert(q);
//创建新节点
QN* newNode = (QN*)malloc(sizeof(QN));
newNode->next = NULL;
newNode->val = data;
if (newNode == NULL) {
perror("malloc");
}
//第一个节点,要对头位置进行修改
if (q->head == NULL) {
q->head = q->tail = newNode;
}
//其余位置都支对尾位置进行修改即可
else {
q->tail->next = newNode;
q->tail = newNode;
}
//有效数据个数加一
q->size++;
}
4)出队
//出队
void QueuePop(Queue* q) {
assert(q);
//判空
assert(q->head);
//仅有一个节点
if (q->head->next == NULL) {
free(q->head);
q->head = NULL;
}
//有两个或以上节点
else {
QN* next = q->head->next;
free(q->head);
q->head = NULL;
q->head = next;
}
q->size--;
}
5)获取队头元素
// 获取队列头部元素
QNDataType QueueFront(Queue* q) {
assert(q);
assert(q->head);
return q->head->val;
}
6)获取队尾元素
// 获取队列队尾元素
QNDataType QueueBack(Queue* q) {
assert(q);
assert(q->head);
return q->tail->val;
}
7)获取队列中元素个数
// 获取队列中有效元素个数
int QueueSize(Queue* q) {
assert(q);
return q->size;
}
8)队列判空
// 检测队列是否为空
bool QueueEmpty(Queue* q) {
assert(q);
return q->head == NULL;
}
9)清空队列
//清空队列
void QueueClear(Queue* q) {
assert(q);
assert(q->head);
//将队列中除首元素节点外的节点释放
QN* t = q->head->next;
while (t) {
QN* next = t->next;
free(t);
t = NULL;
t = next;
}
//将头和尾节点置为NULL
q->head = q->tail = NULL;
}
10)销毁队列
// 销毁队列
void QueueDestroy(Queue* q) {
assert(q);
//将队列中所有空间释放
while (q->head) {
QN* next = q->head->next;
free(q->head);
q->head = NULL;
q->head = next;
}
q->size = 0;
}
1.Queue.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int QNDataType;
typedef struct QueueNode {
QNDataType val;//数据域
struct QueueNode* next;//指针域
}QN;
typedef struct Queue {
QN* head;//头
QN* tail;//尾
int size;//有效数据个数,便于统计个数
}Queue;
// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QNDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QNDataType QueueFront(Queue* q);
// 获取队列队尾元素
QNDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空
bool QueueEmpty(Queue* q);
//清空
void QueueClear(Queue*q);
// 销毁队列
void QueueDestroy(Queue* q);
2.Queue.c
#pragma once
#include"Queue.h"
// 初始化队列
void QueueInit(Queue* q) {
assert(q);
//初始队中无元素,队头、队尾都置为NULL
q->head = q->tail = NULL;
q->size = 0;
}
// 入队
void QueuePush(Queue* q, QNDataType data) {
assert(q);
//创建新节点
QN* newNode = (QN*)malloc(sizeof(QN));
newNode->next = NULL;
newNode->val = data;
if (newNode == NULL) {
perror("malloc");
}
//第一个节点,要对头位置进行修改
if (q->head == NULL) {
q->head = q->tail = newNode;
}
//其余位置都支对尾位置进行修改即可
else {
q->tail->next = newNode;
q->tail = newNode;
}
//有效数据个数加一
q->size++;
}
//出队
void QueuePop(Queue* q) {
assert(q);
//判空
assert(q->head);
//仅有一个节点
if (q->head->next == NULL) {
free(q->head);
q->head = NULL;
}
//有两个或以上节点
else {
QN* next = q->head->next;
free(q->head);
q->head = NULL;
q->head = next;
}
q->size--;
}
// 获取队列头部元素
QNDataType QueueFront(Queue* q) {
assert(q);
assert(q->head);
return q->head->val;
}
// 获取队列队尾元素
QNDataType QueueBack(Queue* q) {
assert(q);
assert(q->head);
return q->tail->val;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q) {
assert(q);
return q->size;
}
// 检测队列是否为空
bool QueueEmpty(Queue* q) {
assert(q);
return q->head == NULL;
}
//清空队列
void QueueClear(Queue* q) {
assert(q);
assert(q->head);
//将队列中除首元素节点外的节点释放
QN* t = q->head->next;
while (t) {
QN* next = t->next;
free(t);
t = NULL;
t = next;
}
//将头和尾节点置为NULL
q->head = q->tail = NULL;
}
// 销毁队列
void QueueDestroy(Queue* q) {
assert(q);
//将队列中所有空间释放
while (q->head) {
QN* next = q->head->next;
free(q->head);
q->head = NULL;
q->head = next;
}
q->size = 0;
}
3.Test.c
#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"
int main() {
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 4);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePop(&q);
int head = QueueFront(&q);
printf("%d\n",head);
int end = QueueBack(&q);
printf("%d\n",end);
int size = QueueSize(&q);
printf("%d\n",size);
bool ret1 = QueueEmpty(&q);
if (ret1 == true) {
printf("空\n");
}
else {
printf("非空\n");
}
QueueClear(&q);
bool ret2 = QueueEmpty(&q);
if (ret2 == true) {
printf("空\n");
}
else {
printf("非空\n");
}
QueueDestroy(&q);
return 0;
}