数据结构入门(C语言版)栈和队列之队列的介绍及实现

这篇具有很好参考价值的文章主要介绍了数据结构入门(C语言版)栈和队列之队列的介绍及实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数据结构入门(C语言版)栈和队列之队列的介绍及实现

队列的概念

什么是队列呢?我们先看下面的图:
数据结构入门(C语言版)栈和队列之队列的介绍及实现
我们可以理解成高速公路上的隧道,根据这个图的描述
我们把需入队的元素看作一辆车,把队列看作隧道,由此我们可以看出
队列的特点是只允许从一端进入,从另一端离开。
队列就是只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头

关于队列的相关名词:

入队:进入队列,即向队列中插入元素
出队:离开队列,即从队列中删除元素
队头:允许出队(删除)的一端
队尾:允许入队(插入)的一端
队头元素:队列中最先入栈的元素
队尾元素:队列中最后入栈的元素

我们可以直接将队头元素看作队头,队尾元素看作队尾。

队列的实现过程

和栈一样,队列也可以有两种实现方式:数组实现的顺序队列和链表实现的链队列,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
1.数组实现队列
数组队列的实现主要有以下两个缺点
内存浪费:用于存储队列元素的数组空间永远不能用于存储该队列的元素,因为元素只能在前端插入,并且 front 的值可能很高,以至于, 在那之前的所有空间,永远无法填满。
数组大小:在某些情况下,如果我们使用数组来实现队列,可能需要扩展队列以插入更多元素,扩展数组大小几乎是不可能的,因此确定正确的数组大小总是一个 队列的数组实现中的问题。
因此在这我们不详细介绍,主要介绍链表实现队列的形式。
2.链表实现队列
链表实现的队列形式我们主要用图的形式来表现,看下图:
数据结构入门(C语言版)栈和队列之队列的介绍及实现

队列的结构体与接口函数的定义

队列的结构体定义
代码如下:

typedef int QDataType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QueueNode;

typedef struct Queue
{
	QueueNode* head;
	QueueNode* tail;
}Queue;

这里我们使用两个结构体嵌套,QueueNode包含了元素和下一级指针,Queue则在QueueNode基础上嵌套了头指针和尾指针记录入队和出队的操作。
队列的接口函数定义
代码如下:

void QueueInit(Queue* pq);// 初始化队列
void QueuePush(Queue* pq, QDataType x);// 队尾入队列
void QueuePop(Queue* pq);// 队头出队列
QDataType QueueFront(Queue* pq);// 获取队列队头元素
QDataType QueueBack(Queue* pq);// 获取队列队尾元素
int QueueSize(Queue* pq);// 获取队列中有效元素个数
bool QueueEmpty(Queue* pq);// 检测队列是否为空,如果为空返回ture,如果不为空返回false
void QueueDestroy(Queue* pq);// 销毁队列

接下来我们就将这几个接口函数来一一实现。

队列的接口实现

①初始化队列(QueueInit)

代码如下:

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
}

初始化没什么好讲的,就是头尾为空就ok。

②队尾入队列(QueuePush)

代码如下:

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	newnode->data = x;
	newnode->next = NULL;

	if (pq->head == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}

首先使用malloc函数动态分配内存,将x赋给newnode的data,下一级指针指向空,
下面分两种情况讨论,第一种是队列为空时,将newnode这个临时结点直接赋给头指针和尾指针,第二种情况是已经有元素的情况下,就将newnode赋给尾结点的next,再将尾指针指向新的结点,完成尾插操作

③队头出队列(QueuePop)

代码如下:

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));//断言队列不为空

	QueueNode* next = pq->head->next;
	free(pq->head);
	pq->head = next;
	if (pq->head == NULL)
	{
		pq->tail = NULL;
	}
}

这里的断言在下面的代码会实现,首先我们要将队头的下一结点赋给临时结点next,
然后释放掉头队头内存空间,再把临时结点next赋给新的队头指针,再考虑删完的情况下,把队尾结点也置空,完成出队操作。

④队头元素(QueueFront)

代码如下:

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));//断言队列不为空

	return pq->head->data;
}

同样断言不为空,然后直接返回头指针的data元素即可。

⑤队尾元素(QueueBack)

代码如下:

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->tail->data;
}

队尾元素也和上面一样,首先断言队列不为空,再直接返回队尾指针的data元素即可。

⑥有效元素个数(QueueSize)

代码如下:

int QueueSize(Queue* pq)
{
	assert(pq);

	int n = 0;
	QueueNode* cur = pq->head;
	while (cur)
	{
		++n;
		cur = cur->next;
	}

	return n;
}

这里我们创建一个临时结点cur,将队头结点赋给它,然后利用while循环对队列进行遍历,临时变量n进行记录,最后返回n的值即为有效元素个数。

⑦检测队列是否为空(QueueEmpty)

代码如下:

bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}

和前面的栈的接口函数一样,这个函数返回类型可以是int,这里我使用bool类型也是一样的,只不过我这返回的是逻辑值true或是false,如果为空返回ture,如果不为空返回false。

⑧销毁队列(QueueDestroy)

代码如下:

void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;
	while (cur != NULL)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;
}

销毁队列的实现和链表是一样的(本来这里的队列就是用链表实现的),首先将队头结点指针赋给临时结点cur,然后遍历每个队列结点,一个一个释放内存空间,最后将队头结点和队尾结点指向空,完成销毁链表操作。

结语

扩展:,实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。这里我们就不讲这么多啦,如果大家有兴趣的话,作者可以单独写一篇博客来讲一讲。

制作不易,如有不正之处敬请指出
感谢大家的来访,UU们的观看是我坚持下去的动力
在时间的催化剂下,让我们彼此都成为更优秀的人吧!!!文章来源地址https://www.toymoban.com/news/detail-414159.html

到了这里,关于数据结构入门(C语言版)栈和队列之队列的介绍及实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】—手把手带你用C语言实现栈和队列(超详细!)

                                       食用指南:本文在有C基础的情况下食用更佳                                     🔥 这就不得不推荐此专栏了:C语言                                   ♈️ 今日夜电波:Tell me —milet                    

    2024年02月14日
    浏览(118)
  • 【数据结构】栈和队列(队列篇)

    上期我们已经学习了数据结构中的栈,这期我们开始学习队列。 目录 1.队列的概念及结构 2.队列的实现 队列结构体定义 常用接口函数 初始化队列 队尾入队列 队头出队列 获取队列头部元素、 获取队列队尾元素 获取队列中有效元素个数 检测队列是否为空 销毁队列 3.循环队

    2024年02月13日
    浏览(42)
  • 栈和队列【数据结构】

    2024年02月16日
    浏览(45)
  • [数据结构】栈和队列

    目录 1.栈 1.1概念 1.2 栈的使用 1.3.栈的模拟实现 2.队列 2.1概念 2.2队列的使用 2.3队列的模拟实现 2.4 循环队列 2.5双端队列   栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素

    2024年02月07日
    浏览(42)
  • 数据结构:栈和队列

    朋友们、伙计们,我们又见面了,本期来给大家解读一下栈和队列方面的相关知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数据结构专栏:数据结构 个 人 主 页 :  stackY、 目录 前言:  1.栈 1.1栈的

    2024年02月06日
    浏览(43)
  • 数据结构【栈和队列】

    一、栈 1.定义:只允许一端进行插入和删除的线性表,结构与手枪的弹夹差不多,可以作为实现递归函数(调用和返回都是后进先出)调用的一种数据结构; 栈顶:允许插入删除的那端; 栈底:固定的,不允许插入或删除; 空栈:不含元素; 2.特点:后进先出; 3.操作:入

    2024年02月15日
    浏览(49)
  • 数据结构 | 栈和队列

    … 📘📖📃本文已收录至:数据结构 | C语言 更多知识尽在此专栏中! 栈(Stack) 又名堆栈,它是一种运算受限的线性表,限定仅在表尾进行插入和删除操作的线性表。 队列(Queue) 也是一种特殊的线性表,特殊之处在于它只允许在表的前端(Front)进行删除操作,而在表的

    2024年01月23日
    浏览(43)
  • 数据结构---栈和队列

    栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作,进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。 出栈:栈的删除操作

    2024年01月18日
    浏览(41)
  • 数据结构--栈和队列

    栈是一种常见的数据结构,它遵循 后进先出LIFO (Last In First Out)的原则。 进行数据插入和操作的一端称为栈顶,另一端称为栈底 。 压栈 :栈的插入操作被称为压栈/进栈/入栈,入数据在栈顶。 出栈 :栈的删除操作。出数据也在栈顶; 栈可以用 数组 或者是 链表 来实现;

    2024年02月09日
    浏览(41)
  • 数据结构——栈和队列

    目录  一.前言 二.前文回顾 三.栈 3.1 栈的概念及结构 3.2 栈的实现 3.2.1 初始化函数 3.2.2 销毁函数 3.2.3 入栈函数 3.2.4 出栈函数 3.2.5 计算大小函数 3.2.6 空栈函数 3.2.7 获取栈顶函数  3.2.8 小测试 3.3 全部代码 四.栈的练习 4.1 有效的括号 五.队列 5.1队列的概念及结构 5.2 队列的实

    2024年01月25日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包