首页 > 编程语言 >C语言数据结构与算法(栈和队列)

C语言数据结构与算法(栈和队列)

时间:2025-01-04 20:34:04浏览次数:7  
标签:队列 代码 栈顶 C语言 实现 数组 数据结构 数据

1.栈

1.栈的概念及结构

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

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶

出栈:栈的删除操作叫做出栈。出数据也在栈顶

压栈和出栈也遵循后进先出原则

1.2栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。

进栈和出栈示意图:

                        

1.2.1结构设定

利用动态数组实现。

                                

1.2.2初始化

由于是使用动态数组实现的,我们需将数组在初始化是开一些空间,并对结构体中的capaci(容量)和top(指向栈顶的数组下标)进行初始化。

代码实现:

                        

1.2.3入栈

由于是用动态数组实现的。

注意:

①入栈前需判断是否需要扩容。

②Top是指向栈顶的,入栈时应将Top++,在进行入栈。

代码实现及其图解:

                                

1.2.4出栈

注意:

①需判断栈是否为空。

②直接将Top--,由于数组是依靠下标访问的。

代码实现及其图解:

                                

                

1.2.5访问栈顶数据

由于我们前面初始化就将Top指向栈顶数据的下标,因此这里我们直接访问数组的TOP下标即可。

注意:要判断栈是否为空。

代码实现:

                        

1.2.6栈的数据个数

Top指向的是栈顶元素,我们统计栈里的数据个数我们只需要将Top+1即可。

代码实现:

                   

1.2.7销毁

我们是用动态数组实现的,使用完后需将开辟在堆上的数据释放掉,否则会出现内存泄漏。

代码实现:

                

2.队列

2.1队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头。

2.2队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

2.2.1结构设定

①定义链表的结构体

②由于队列涉及链表的头删和尾插,故我们需要在封装个结构体用于指向链表的头节点(对头)和尾节点(队尾),比较高效因此不用遍历链表来找头和尾。

代码实现及其示意图:

head用于指向队头

tail用于指向队尾

size用于记录队列中的数据个数。

2.2.2初始化

对指向头和尾的结构体初始化即可,由于我们队列是依靠此结构体来运行的。

代码实现:

                

2.2.3判断队列是否为空

直接访问size即可,看其是否为零或者看其头和尾指针是否都指向NULL。为空返回 true,不为空则返回 false。

代码实现:

                

2.2.4入队列

入列:即链表的尾插(需注意:①是否为空链表②非空链表)

代码实现及其示意图:

2.2.5出队列

注意:

①队列只有一个数据。

②队列有多个数据。

代码实现及其图解:

2.2.6访问队头数据

由于刚开始就定义了个结构体里面的head和tail指针分别指向队头和队尾,因此可直接访问。

注意:要判断队列是否为空。

代码实现:

                

2.2.7访问队尾数据

同访问队头数据一样的原理。

代码实现:

                

2.2.8队列的数据个数

直接访问结构体中的size。

代码实现:

                

2.2.9销毁

将开在堆上的链表节点释放,返回给操作系统。

代码实现:

                

3.用两个队列实现栈

用两个队列的基础上实现完成栈的功能(遵循后进先出)。后面所用的函数都是上面队列的实现的函数。

3.1结构体初始化

须在实现的队列的基础上加多个结构体,成员是两个队列。

代码实现及图解:

3.2初始化

对存放两个队列的结构体进行初始化。

代码实现:

                 

3.3入栈

遵循得出两个队列实现栈的原理:入数据往空队列入。

代码实现及解析:

3.4出栈

把不为空的队列的数据,导入到另一个空队列中,直到剩一个元素(即为要出栈的元素)。

代码实现及解析:

3.5访问栈顶元素

由于我们在队列的实现中,添加了访问队尾的数据(即为栈顶元素)的函数。我们只需要判断一下那个是不为空的队列,然后访问其队尾元素,即可得到我们想要的栈顶元素。

代码实现:

        

3.6判断栈是否为空

我们只需要判断那两个队列中是否为空,为空则为空栈。

代码实现:

3.7销毁

需先销毁结构体中的两个队列,最后在销毁存放两个队列的结构体。

代码实现:

        

4.用两个栈实现队列

遵循先进先出原则。沿用上面栈的实现的接口,两个栈来实现队列具有的性质。和上面两个队列实现栈的原理有点不一样。

原理:(通过画图观察得到)

①一个栈只用来入数据

②另一个栈只用来出数据

4.1结构体的设定

根据原理得,一个栈用来入数据,另一个栈用来出数据,结构体要有两个栈。

代码实现及结构体图示:

4.2初始化

首先需要malloc个结构体(存放两个栈的),然后利用实现栈的初始化,对结构体中的两栈进行初始化即可。

代码实现:

4.3入队列

往专门入数据的那个栈存放数据即可。

代码实现:

                

4.4访问队头数据

注意:

①判断出数据的那个栈是否为空,不为空则直接沿用栈的实现访问栈顶元素的函数(即为队头数据),由于专门出数据的栈,栈里的数据是由入数据哪里倒过来的,所以栈顶元素的数据就是队头数据。 

②出数据的栈为空,需要从入数据的栈,将专门负责入数据的栈的全部数据导入出数据的栈中,然后访问出数据的栈的栈顶元素即可。

代码实现及解析:

        

4.5出队列

①若是专门负责出数据的栈不为空,则直接pop其栈顶数据即可。

若是专门负责出数据的栈为空,则需要将负责专门入数据的栈,入数据的栈里的元素全部导入出数据的栈中,最后pop出数据的栈的栈顶元素即可。

代码实现:原理和上面的访问队头数据一样。

4.6队列是否为空

判断那两个栈是否为空。

代码实现:

4.7销毁

先销毁两个栈,最后再销毁存放两个栈的结构体。

代码实现:

        

5.循坏队列

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。遵循先进先出原则可以用数组实现也可以用链表实现,数组实现的话建议开多一个位置,较容易理解和实现;若是用链表实现的话:解决方案一:结构体中加多个变量size用来记录有效数据的个数。解决方案二:开多一个节点。这里我选择使用数组来实现(当数组超过某个值的时候对其 % 上一个数(k+1)即可控制,防止数组的越界访问)。

5.1结构体的设定

数组实现

代码实现:

                

5.2初始化

首先malloc个结构体,然后在对其成员进行初始化,数组需要开辟k+1个整型空间,front和rear都为零。

代码实现:

                

5.3判断循环队列是否为空

当结构体中的front和rear相等时循环队列才为空。

代码实现及图示:

                        

5.4判断循环队列是否已满

代码实现及图解:

5.5向循环队列插入一个数据

①判断循环队列是否已满。

②特殊情况如下。

代码实现及图示:

5.6从循环队列中删除一个数据

注意:要判断循环队列是否为空。

代码实现及图解:

                        

5.7访问队头元素数据

注意:要判断循环队列是否为空。

代码实现及解析:

        

5.8访问队尾元素数据

注意:有特殊情况如下图。

代码实现及图解:

        

5.9销毁

由于我们数组和结构体都是开在堆上的,故需要 free,将内存空间还给操作系统。

代码实现:

欢迎大家的指导与交流,希望对大家有所帮助,觉得不错的别忘记点赞+收藏咯!!!

谢谢大家。

标签:队列,代码,栈顶,C语言,实现,数组,数据结构,数据
From: https://blog.csdn.net/2301_81978155/article/details/144868279

相关文章

  • C语言:三子棋plus版本如约而至
    唉,想了好久,这才想出一个可行的方案,来与大家分享,也希望鄙人的想法可以抛砖引玉,让大家有更多的想法来完善这个游戏,话不多说,让我们开始吧(阅读提醒,希望各位先把鄙人先前写的三子棋的游戏的博客先看一看再来阅读此文)OK,我们这次的主要任务就是完善电脑下棋,致力于写一个更加完善的AI,n......
  • 03专升本数据结构笔记 第三章:栈和队列
    专升本数据结构笔记第三章:栈和队列阿洛学长笔记lovettz栈和队列任务一栈的定义、存储结构和基本操作(阿洛学长)一、栈的定义及其基本操作二、栈的顺序存储结构三、栈的链式存储结构四、栈在递归中的应用一、栈的定义及其基本操作1.栈的定义栈是一种只允许在表的......
  • 02专升本数据结构笔记 第二章:线性表
    专升本数据结构笔记第二章:线性表阿洛学长笔记lovettz线性表任务一线性表的定义和基本操作(阿洛学长)一、线性表的定义线性表是由n(n≥0)个类型相同的数据元素a1,a2,…,an组成的有限序列,数据元素之间是一对一的关系,记作L=(a1,a2,…,ai-1,ai,ai+1,…,an)(由n(n≥0)个......
  • C语言的其他关键字
    数据类型enum枚举,为一个变量定义一组命名的整数常量,或者更简单点就是给一组变量(一般是相关的)起一个统一的名字,这一组变量在其中就会有一个对应的整数常量,从0开始依次递增,也可显式指定,之后的依次递增,可以用这个名字.变量名的格式进行使用,对应的整数值主要是为了内部表示和可能......
  • 【java-数据结构篇】神奇 ArrayList,一键打印扑克牌花色与点数
    我的个人主页我的专栏:Java-数据结构,希望能帮助到大家!!!点赞❤收藏❤前言:在编程的奇妙世界里,数据结构如同精巧的积木,搭建起各类功能的大厦。而ArrayList,作为其中一块极为实用的“积木”,拥有着独特的魅力与强大的功能。当我们将目光投向生活中的趣味场景——扑克牌......
  • c语言文件操作
    1.为什么使用文件(将数据记录保存)我们前面学习结构体时,写了通讯录的程序,当通讯录运行起来的时候,可以给通讯录中增加、删除数据,此时数据是存放在内存中,当程序退出的时候,通讯录中的数据自然就不存在了,等下次运行通讯录程序的时候,数据又得重新录入,如果使用这样的通讯录就很难受......
  • 数据流的中位数(优先队列)
    中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。例如 arr=[2,3,4] 的中位数是 3 。例如 arr=[2,3] 的中位数是 (2+3)/2=2.5 。实现MedianFinder类:MedianFinder()初始化 MedianFinder 对象。vo......
  • C语言实现通讯录(静态的版本)
    通讯录的实现框架静态的版本实现一个通讯录:人的信息:名字+年龄+性别+电话+地址1.存放100个人的信息2.增加联系人3.删除指定联系人4.查找联系人5.修改联系人6.显示联系人7.排序测试功能test.c通讯录相关的实现contact.c通讯录相关的声明contact.h......
  • 前k个高频元素(优先队列)
    给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例1:输入:nums=[1,1,1,2,2,3],k=2输出:[1,2]示例2:输入:nums=[1],k=1输出:[1]classSolution{public:vector<int>topKFreque......
  • 数据结构:包装类和泛型
    目录一、包装类1、基本数据类型和对应的包装类 2、装箱和拆箱 3、自动装箱和自动拆箱 二、泛型 1、什么是泛型2、泛型语法 3、泛型类 4、擦除机制 5、泛型的上界 6、泛型方法三、通配符 1、什么是通配符 2、通配符上界 3、通配符下界 ......