【C++】数据结构 队列的实现

本篇博客给大家带来的是用C++语言来实现数据结构的队列的实现!

🐟🐟文章专栏:数据结构

🚀🚀若有问题评论区下讨论,我会及时回答

❤❤欢迎大家点赞、收藏、分享!

今日思想:你现在的懒惰将来你会买单的!

一、队列的定义

队列就像上面的那一根水管,数据只能从后面流入从前面流出。

二、队列的实现

队列的实现我们用链表的形式来实现,具有先进先出的特点。那么队列实现的方法有: 队列的初始化、队列的销毁、入队------队尾、出队------队头、取队头数据、取队尾数据、判断队列是否为空、队列的有效元素个数。接下来我们一一实现。

1、队列的初始化

既然队列是链表构成,那么我们要定义一个链表的结构体,还要定义一个结构体来记录队头和队尾的指向和数据的个数。

如图:

代码实例:

cpp 复制代码
//Queue.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

//定义结点的结构
typedef int QDataType;
typedef struct QueueNode
{
	QDataType* data;
	struct QueueNode* next;
}QueueNode;

//定义队列的结构
typedef struct Queue
{
	QueueNode* phead;//队头
	QueueNode* ptail;//队尾
	int size;//有效数据个数
}Queue;

队列的初始化:

代码实例:

cpp 复制代码
//Queue.h
//队列的初始化
void QueueInit(Queue* pq);
cpp 复制代码
//Queue.c
//队列的初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
}

2、队列的销毁

这里队列的初始化和销毁较为简单就不展开讲了,直接上代码。

代码实例:

cpp 复制代码
//Queue.h
//队列的销毁
void QueueDestroy(Queue* pq);
cpp 复制代码
//Queue.c
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* pcur = pq->phead;
	while (pcur)
	{
		QueueNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pq->phead = pq->ptail = NULL;
}

3、入队------队尾

当我们插入一个数据时候我们看看这个链表是否为空或者只有一个结点,那么phead和ptail都指向第一个结点,我们每插一个数据时就要向操作系统申请一个结点来存储数据,这时我们让这个结点的next指向NULL,如果是多个结点那么直接尾插,数据一旦增加那么size也要加一。

代码实例:

cpp 复制代码
//Queue.h
//入队------队尾
void QueuePush(Queue* pq, QDataType x);
cpp 复制代码
//Queue.c
//入队------队尾
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;

	//队列为空,newnode是队头也是队尾
	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		//队列非空,直接插入队尾
		pq->ptail->next = newnode;
		pq->ptail = pq->ptail->next;
	}
	pq->size++;
}

4、判断队列是否为空

代码实例:

cpp 复制代码
//Queue.h
//判断队列是否为空
bool QueueEmpty(Queue* pq);
cpp 复制代码
//Queue.c
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == 0;
}

5、出队------队头

假如我们插入1234, 那么1先进去也要先出来,所以从phead那里拿数据就行,然后改变phead的指向,size也要减一。

代码实例:

cpp 复制代码
//Queue.h
//出队------队头
void QueuePop(Queue* pq); 
cpp 复制代码
//Queue.c
//出队------队头
void QueuePop(Queue* pq)
{
	assert(!QueueEmpty(pq));
	//只有一个结点的情况
	if (pq->phead == pq->ptail)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QueueNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}

6、取队头数据

无论是取队头数据还是取队尾数据,思路较为简单,不展开讲。

代码实例:

cpp 复制代码
//Queue.h
//取队头数据
QDataType QueueFront(Queue* pq);
cpp 复制代码
//Queue.c
//取队头数据
QDataType QueueFront(Queue* pq)
{
	assert(!QueueEmpty(pq));
	return pq->phead->data;
}

7、取队尾数据

代码实例:

cpp 复制代码
//Queue.h
//取队尾数据
QDataType* QueueBack(Queue* pq);
cpp 复制代码
//Queue.c
//取队尾数据
QDataType* QueueBack(Queue* pq)
{
	assert(!QueueEmpty(pq));
	return pq->ptail->data;
}

8、队列有效元素个数

这里的有效元素个数其实就是存储的数据有多少个即size。

代码实例:

cpp 复制代码
//Queue.h
//队列有效元素个数
int QueuueSize(Queue* pq);
cpp 复制代码
//Queue.c
//队列有效元素个数
int QueuueSize(Queue* pq)
{
	return pq->size;
}

完!!

完整代码如下:

cpp 复制代码
//Queue.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

//定义结点的结构
typedef int QDataType;
typedef struct QueueNode
{
	QDataType* data;
	struct QueueNode* next;
}QueueNode;

//定义队列的结构
typedef struct Queue
{
	QueueNode* phead;//队头
	QueueNode* ptail;//队尾
	int size;//有效数据个数
}Queue;

//队列的初始化
void QueueInit(Queue* pq);
//队列的销毁
void QueueDestroy(Queue* pq);
//入队------队尾
void QueuePush(Queue* pq, QDataType x);
//出队------队头
void QueuePop(Queue* pq); 
//取队头数据
QDataType QueueFront(Queue* pq);
//取队尾数据
QDataType* QueueBack(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//队列有效元素个数
int QueuueSize(Queue* pq);
cpp 复制代码
//Queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"

//队列的初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
}

//队列的销毁
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* pcur = pq->phead;
	while (pcur)
	{
		QueueNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pq->phead = pq->ptail = NULL;
}

//入队------队尾
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;

	//队列为空,newnode是队头也是队尾
	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		//队列非空,直接插入队尾
		pq->ptail->next = newnode;
		pq->ptail = pq->ptail->next;
	}
	pq->size++;
}

//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == 0;
}

//出队------队头
void QueuePop(Queue* pq)
{
	assert(!QueueEmpty(pq));
	//只有一个结点的情况
	if (pq->phead == pq->ptail)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QueueNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}

//取队头数据
QDataType QueueFront(Queue* pq)
{
	assert(!QueueEmpty(pq));
	return pq->phead->data;
}

//取队尾数据
QDataType* QueueBack(Queue* pq)
{
	assert(!QueueEmpty(pq));
	return pq->ptail->data;
}

//队列有效元素个数
int QueuueSize(Queue* pq)
{
	return pq->size;
}
相关推荐
罗西的思考21 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
CSharp精选营1 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
美团技术团队1 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境2 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
_清歌2 天前
DSpark 深度解读:DeepSeek-V4 如何用「半自回归」把推理速度提升 85%
算法