数据结构——队列的基本操作

前言

介绍

🍃数据结构专区:数据结构

参考

该部分知识参考于《数据结构(C语言版 第2版)》24~28页

🌈每一个清晨,都是世界对你说的最温柔的早安:ૢ(≧▽≦)و✨


目录

前言

1、队列的基本概念

2、基于数组的队列

[2.1 宏定义](#2.1 宏定义)

[2.2 数组队列的结构体定义](#2.2 数组队列的结构体定义)

[2.3 队列的初始化](#2.3 队列的初始化)

[2.4 销毁队列](#2.4 销毁队列)

[2.5 求队列长度](#2.5 求队列长度)

[2.6 入队](#2.6 入队)

[2.7 出队](#2.7 出队)

[2.8 获取队头元素](#2.8 获取队头元素)

[2.9 遍历打印](#2.9 遍历打印)

[2.10 整体代码(含测试)](#2.10 整体代码(含测试))

3、基于链表的队列

[3.1 宏定义](#3.1 宏定义)

[3.2 链表队列的结构体定义](#3.2 链表队列的结构体定义)

[3.3 队列的初始化](#3.3 队列的初始化)

[3.4 销毁队列](#3.4 销毁队列)

[3.5 求队列中元素个数](#3.5 求队列中元素个数)

[3.6 入队](#3.6 入队)

[3.7 出队](#3.7 出队)

[3.8 获取队头元素](#3.8 获取队头元素)

[3.9 输出队列元素](#3.9 输出队列元素)

[3.10 整体代码(含测试)](#3.10 整体代码(含测试))

结语


1、队列的基本概念

队列(Queue)是一种特殊的线性表 ,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。这种操作原则使得队列具有**先进先出(FIFO, First In First Out)**的特性。

  • 基于数组的队列:在这种实现中,队列被限制在一个固定大小的数组中。需要维护两个指针,一个指向队首(front),另一个指向队尾(rear)。当进行入队操作时,如果rear指针指向数组的最后一个位置,且队列未满,可能需要将队列中的元素整体向前移动(或称为"循环"数组),以为新元素腾出空间。
  • 基于链表的队列:在这种实现中,队列由节点组成的链表来表示。每个节点包含数据部分和指向下一个节点的指针。队首和队尾分别由两个指针(head和tail)来维护。这种实现方式更加灵活,因为它不需要预先分配固定大小的存储空间,并且可以在常数时间内完成入队和出队操作。

2、基于数组的队列

2.1 宏定义

cpp 复制代码
#include<iostream>
using namespace std;

//初始化定义
#define OK 1
#define ERROR 0
#define OVERFLOW -1
//Status是函数返回值类型,其值是函数结果状态代码
typedef int Status;

2.2 数组队列的结构体定义

cpp 复制代码
#define MAXQSIZE 100  //队列可能达到的最大长度
typedef int QElemType;
typedef struct
{
	QElemType* base;  //存储空间的基地址
	int front;        //头指针
	int rear;         //尾指针
}SqQueue;

//队空的条件:Q.front == Q.rear
//队满的条件:(Q.rear + 1) % MAXQSIZE == Q.front

2.3 队列的初始化

cpp 复制代码
//队列初始化
Status InitQueue(SqQueue& Q)
{
	//构造一个空队列Q
	Q.base = new QElemType[MAXQSIZE];  //为队列分配一个最大容量为MAXQSIZE的数组空间
  //Q.base = (int*)malloc(MAXQSIZE * sizeof(int));
	if (!Q.base)
		exit(OVERFLOW);      //如果开辟失败就退出程序
	Q.front = Q.rear = 0;    //头尾指针指向0,表示队列为空
	return OK;
}

2.4 销毁队列

cpp 复制代码
// 销毁队列
Status DestroyQueue(SqQueue& Q)
{
	if (Q.base) {
		delete[] Q.base;
		Q.base = NULL;
		Q.front = Q.rear = 0;
	}
	return OK;
}

2.5 求队列长度

cpp 复制代码
//求队列长度
int QueueLength(SqQueue Q)
{
	//返回队列元素个数
	return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}

2.6 入队

cpp 复制代码
//入队
Status EnQueue(SqQueue& Q, QElemType e)
{
	//插入元素e为Q的新的队尾元素
	if ((Q.rear + 1) % MAXQSIZE == Q.front)
		return ERROR;    //若尾指针在循环意义上加1后等于头指针,表明队满
	Q.base[Q.rear] = e;     //新元素插入队尾
	Q.rear = (Q.rear + 1) % MAXQSIZE;     //队尾指针加1
	return OK;
}

2.7 出队

cpp 复制代码
//出队
Status DeQueue(SqQueue& Q, QElemType& e)
{
	//删除队头元素,用e返回其值
	if (Q.front == Q.rear)
		return ERROR;  //队空
	e = Q.base[Q.front];
	Q.front = (Q.front + 1) % MAXQSIZE;
	return OK;
}

2.8 获取队头元素

cpp 复制代码
//取队头元素
QElemType GetHead(SqQueue Q)
{
	//返回队头元素,不改变头指针
	if (Q.front != Q.rear)  //队列非空
		return Q.base[Q.front];
}

2.9 遍历打印

cpp 复制代码
//输出队列元素
void PrintQueue(SqQueue& Q)
{
	printf("(front) ");
	int i;
	for (i = Q.front; i != Q.rear; i++)
	{
		printf("%d ", Q.base[i]);
	}
	printf("(rear)\n");
}

2.10 整体代码(含测试)

cpp 复制代码
#include<iostream>
using namespace std;

//初始化定义
#define OK 1
#define ERROR 0
#define OVERFLOW -1
//Status是函数返回值类型,其值是函数结果状态代码
typedef int Status;

#define MAXQSIZE 100  //队列可能达到的最大长度
typedef int QElemType;
typedef struct
{
	QElemType* base;  //存储空间的基地址
	int front;        //头指针
	int rear;         //尾指针
}SqQueue;

//队空的条件:Q.front == Q.rear
//队满的条件:(Q.rear + 1) % MAXQSIZE == Q.front

//队列初始化
Status InitQueue(SqQueue& Q)
{
	//构造一个空队列Q
	Q.base = new QElemType[MAXQSIZE];  //为队列分配一个最大容量为MAXQSIZE的数组空间
  //Q.base = (int*)malloc(MAXQSIZE * sizeof(int));
	if (!Q.base)
		exit(OVERFLOW);      //如果开辟失败就退出程序
	Q.front = Q.rear = 0;    //头尾指针指向0,表示队列为空
	return OK;
}

// 销毁队列
Status DestroyQueue(SqQueue& Q)
{
	if (Q.base) {
		delete[] Q.base;
		Q.base = NULL;
		Q.front = Q.rear = 0;
	}
	return OK;
}

//求队列长度
int QueueLength(SqQueue Q)
{
	//返回队列元素个数
	return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}

//入队
Status EnQueue(SqQueue& Q, QElemType e)
{
	//插入元素e为Q的新的队尾元素
	if ((Q.rear + 1) % MAXQSIZE == Q.front)
		return ERROR;    //若尾指针在循环意义上加1后等于头指针,表明队满
	Q.base[Q.rear] = e;     //新元素插入队尾
	Q.rear = (Q.rear + 1) % MAXQSIZE;     //队尾指针加1
	return OK;
}

//出队
Status DeQueue(SqQueue& Q, QElemType& e)
{
	//删除队头元素,用e返回其值
	if (Q.front == Q.rear)
		return ERROR;  //队空
	e = Q.base[Q.front];
	Q.front = (Q.front + 1) % MAXQSIZE;
	return OK;
}

//取队头元素
QElemType GetHead(SqQueue Q)
{
	//返回队头元素,不改变头指针
	if (Q.front != Q.rear)  //队列非空
		return Q.base[Q.front];
}

//输出队列元素
void PrintQueue(SqQueue& Q)
{
	printf("(front) ");
	int i;
	for (i = Q.front; i != Q.rear; i++)
	{
		printf("%d ", Q.base[i]);
	}
	printf("(rear)\n");
}

int main()
{
	SqQueue Q;
	QElemType e;

	cout << "初始化队列..." << endl;
	if (InitQueue(Q) == OK)
		cout << "队列初始化成功!" << endl;
	else
		cout << "队列初始化失败!" << endl;

	cout << "\n测试入队操作:" << endl;
	for (int i = 1; i <= 5; i++)
	{
		if (EnQueue(Q, i) == OK)
			cout << i << " 入队成功" << endl;
		else
			cout << i << " 入队失败" << endl;
	}

	cout << "\n当前队列:" << endl;
	PrintQueue(Q);

	cout << "\n队列长度:" << QueueLength(Q) << endl;

	cout << "\n测试出队操作:" << endl;
	for (int i = 0; i < 3; i++)
	{
		if (DeQueue(Q, e) == OK)
			cout << e << " 出队成功" << endl;
		else
			cout << "出队失败,队列可能为空" << endl;
	}

	cout << "\n当前队列:" << endl;
	PrintQueue(Q);

	cout << "\n队列长度:" << QueueLength(Q) << endl;

	cout << "\n队头元素:" << GetHead(Q) << endl;

	cout << "\n销毁队列..." << endl;
	if (DestroyQueue(Q) == OK)
		cout << "队列销毁成功!" << endl;
	else
		cout << "队列销毁失败!" << endl;

	return 0;
}

3、基于链表的队列

3.1 宏定义

cpp 复制代码
//链队列的实现
#include<iostream>
using namespace std;

//初始化定义
#define OK 1
#define ERROR 0
#define OVERFLOW -1
//Status是函数返回值类型,其值是函数结果状态代码
typedef int Status;

3.2 链表队列的结构体定义

cpp 复制代码
typedef int QElemType;
typedef struct QNode
{
	QElemType data;
	struct QNode* next;
}QNode, *QueuePtr;

typedef struct
{
	QueuePtr front;   //队头指针
	QueuePtr rear;    //队尾指针
}LinkQueue;

3.3 队列的初始化

cpp 复制代码
//队列初始化
Status InitQueue(LinkQueue& Q)
{
	//构造一个空队列
	Q.front = Q.rear = new QNode;  //生成新结点作为头结点,队头和队尾指针指向此结点
	Q.front->next = NULL;   //头结点的指针域置空
	return OK;
}

3.4 销毁队列

cpp 复制代码
//销毁队列
Status DestroyQueue(LinkQueue& Q)
{
	while (Q.front)
	{
		Q.rear = Q.front->next;
		delete Q.front;
		Q.front = Q.rear;
	}
	return OK;
}

3.5 求队列中元素个数

cpp 复制代码
//求队列中元素数量
int QueueLength(LinkQueue Q)
{
	int count = 0;
	QNode* p = Q.front->next;
	while (p)
	{
		count++;
		p = p->next;
	}
	return count;
}

3.6 入队

cpp 复制代码
//入队
Status EnQueue(LinkQueue& Q, QElemType e)
{
	//插入元素e为Q的新的队尾元素
	QNode* p = new QNode;
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;   //将新结点插入队尾
	Q.rear = p;         //修改队尾指针
	return OK;
}

3.7 出队

cpp 复制代码
//出队
Status DeQueue(LinkQueue& Q, QElemType& e)
{
	//删除队头元素,用e返回其值
	if (Q.front == Q.rear)
		return ERROR;   //若队列为空,返回ERROR
	QNode* p = Q.front->next;
	e = p->data;  //用e保存头结点数据
	Q.front->next = p->next;  //修改头结点指针域
	if (Q.rear == p)
		Q.rear = Q.front;  //最后一个元素被删除,队尾指针指向头结点
	delete p;   //释放原队头元素的空间
	return OK;
}

3.8 获取队头元素

cpp 复制代码
//取队头元素
QElemType GetHead(LinkQueue Q)
{
	//返回Q的队头元素,不修改头指针
	if (Q.front != Q.rear)
		return Q.front->next->data;  //返回头元素的值,队头元素不变
}

3.9 输出队列元素

cpp 复制代码
//输出队列元素
void PrintQueue(LinkQueue Q)
{
	//前提队列不为空
	printf("(front) ");
	if (Q.front != Q.rear)
	{
		QNode* p = Q.front->next;
		while (p != NULL)
		{
			printf("%d ", p->data);
			p = p->next;
		}
	}
	printf("(rear)\n");
}

3.10 整体代码(含测试)

cpp 复制代码
//链队列的实现
#include<iostream>
using namespace std;

//初始化定义
#define OK 1
#define ERROR 0
#define OVERFLOW -1
//Status是函数返回值类型,其值是函数结果状态代码
typedef int Status;

typedef int QElemType;
typedef struct QNode
{
	QElemType data;
	struct QNode* next;
}QNode, *QueuePtr;

typedef struct
{
	QueuePtr front;   //队头指针
	QueuePtr rear;    //队尾指针
}LinkQueue;

//队列初始化
Status InitQueue(LinkQueue& Q)
{
	//构造一个空队列
	Q.front = Q.rear = new QNode;  //生成新结点作为头结点,队头和队尾指针指向此结点
	Q.front->next = NULL;   //头结点的指针域置空
	return OK;
}

//销毁队列
Status DestroyQueue(LinkQueue& Q)
{
	while (Q.front)
	{
		Q.rear = Q.front->next;
		delete Q.front;
		Q.front = Q.rear;
	}
	return OK;
}

//求队列中元素数量
int QueueLength(LinkQueue Q)
{
	int count = 0;
	QNode* p = Q.front->next;
	while (p)
	{
		count++;
		p = p->next;
	}
	return count;
}

//入队
Status EnQueue(LinkQueue& Q, QElemType e)
{
	//插入元素e为Q的新的队尾元素
	QNode* p = new QNode;
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;   //将新结点插入队尾
	Q.rear = p;         //修改队尾指针
	return OK;
}

//出队
Status DeQueue(LinkQueue& Q, QElemType& e)
{
	//删除队头元素,用e返回其值
	if (Q.front == Q.rear)
		return ERROR;   //若队列为空,返回ERROR
	QNode* p = Q.front->next;
	e = p->data;  //用e保存头结点数据
	Q.front->next = p->next;  //修改头结点指针域
	if (Q.rear == p)
		Q.rear = Q.front;  //最后一个元素被删除,队尾指针指向头结点
	delete p;   //释放原队头元素的空间
	return OK;
}

//取队头元素
QElemType GetHead(LinkQueue Q)
{
	//返回Q的队头元素,不修改头指针
	if (Q.front != Q.rear)
		return Q.front->next->data;  //返回头元素的值,队头元素不变
}

//输出队列元素
void PrintQueue(LinkQueue Q)
{
	//前提队列不为空
	printf("(front) ");
	if (Q.front != Q.rear)
	{
		QNode* p = Q.front->next;
		while (p != NULL)
		{
			printf("%d ", p->data);
			p = p->next;
		}
	}
	printf("(rear)\n");
}

int main()
{
	LinkQueue Q;
	QElemType e;

	cout << "初始化队列..." << endl;
	if (InitQueue(Q) == OK)
		cout << "队列初始化成功!" << endl;
	else
		cout << "队列初始化失败!" << endl;

	cout << "\n测试入队操作:" << endl;
	for (int i = 1; i <= 5; i++)
	{
		if (EnQueue(Q, i) == OK)
			cout << i << " 入队成功" << endl;
		else
			cout << i << " 入队失败" << endl;
	}

	cout << "\n当前队列:" << endl;
	PrintQueue(Q);

	cout << "\n队列长度:" << QueueLength(Q) << endl;

	cout << "\n测试出队操作:" << endl;
	for (int i = 0; i < 3; i++)
	{
		if (DeQueue(Q, e) == OK)
			cout << e << " 出队成功" << endl;
		else
			cout << "出队失败,队列可能为空" << endl;
	}

	cout << "\n当前队列:" << endl;
	PrintQueue(Q);

	cout << "\n队列长度:" << QueueLength(Q) << endl;

	cout << "\n队头元素:" << GetHead(Q) << endl;

	cout << "\n销毁队列..." << endl;
	if (DestroyQueue(Q) == OK)
		cout << "队列销毁成功!" << endl;
	else
		cout << "队列销毁失败!" << endl;

	return 0;
}

结语

到此我们队列的基本操作也就完成了,那么我们对于数据结构中的顺序表、栈、队列的学习已经基本完成,可以进行一些简单的力扣题的书写了,这里并没有太大的难度,需要的是不断去熟悉和练习来完成对这部分知识的掌握!

相关推荐
️南城丶北离1 小时前
[数据结构]图——C++描述
数据结构··最小生成树·最短路径·aov网络·aoe网络
✿ ༺ ོIT技术༻1 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
菜鸡中的奋斗鸡→挣扎鸡8 小时前
滑动窗口 + 算法复习
数据结构·算法
axxy20009 小时前
leetcode之hot100---240搜索二维矩阵II(C++)
数据结构·算法
Uu_05kkq11 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法
1nullptr13 小时前
三次翻转实现数组元素的旋转
数据结构
TT哇13 小时前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
A懿轩A13 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
1 9 J14 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
汝即来归14 小时前
选择排序和冒泡排序;MySQL架构
数据结构·算法·排序算法