当前位置: 首页 > news >正文

C语言栈的含义与栈数据操作代码详解!

引言:在本篇博客中,我们将学到数据结构——栈,讲到栈的含义与关于栈的数据操作代码可以在顺序表、双向链表以及单链表的基础上实现,而于本篇博客中,我们选择在顺序表的基础上实现

更多有关C语言和数据结构知识详解可前往个人主页:计信猫

目录

 

一,栈的含义

二,栈的结构体的定义

三,栈数据操作函数

1,栈的初始化

2,栈的销毁

3,入栈

 

4,出栈

5,取栈顶的数据

6,获取栈中数据的个数

7,判断栈是否为空

四,结语


一,栈的含义

        是一种特殊的线性表,只允许在表中固定的一端进行插入和删除元素的操作。进行数据插入和删除操作的一端成为栈顶,另一端成栈底

压栈:栈的数据插入操作。

出栈:栈的数据删除操作。

        而因为特殊的数据插入和删除遵循LIFO(后进先出)的原则,使得可以被比作一个羽毛筒。(因为羽毛球里边的球都是从最上边开始使用的,类比于栈顶

二,栈的结构体的定义

        这次,我们仍然使用三文件操作法,分别创建stack.h、stack.c、test.c三个文件。

         因为前文提到,栈是一种特殊的顺序表,那么栈的定义应该和顺序表的定义方式极其相似,所以在stack.h中,我们如下定义栈:

//包含实现栈的操作函数所要用到的头文件
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int STDataType;
//创建栈结构体
typedef struct Stack
{STDataType* a;//动态数组int top;//栈顶的下一位int capacity;//数组总空间大小
}ST;

        可能大家会不理解top的含义,那么请看如下的图片讲解吧。

 

        如果里边没有元素的时候,那么此时top便指向数组中下标为零的地方。 

三,栈数据操作函数

        因为是在顺序表的基础上实现的,所以的数据操作函数与顺序表及其类似,甚至更简单,好好听吧,一定可以听懂!

1,栈的初始化

        对于栈的初始化其实就是将栈结构体中的指针类型赋值为NULL整型类型赋值为0就可以了,我们直接上代码:

// 初始化栈 
void StackInit(ST* ps)
{//断言判断栈不为NULLassert(ps);ps->a = NULL;ps->capacity = ps->top = 0;//top指向栈顶数据的下一位
}

2,栈的销毁

        在该函数中,我们所需要做的就是释放掉动态数组所开辟的空间,再将指针置空防止野指针的出现,最后将整型类型改为0就可以了。代码如下:

// 销毁栈 
void StackDestroy(ST* ps)
{free(ps->a);//释放动态数组空间ps->a = NULL;//防止野指针的出现ps->capacity = ps->top = 0;
}

3,入栈

        入栈顾名思义,就是在栈顶插入数据

        而在插入数据之前,我们就需要先判断动态数组的空间是否足够,不够我们就使用realloc函数进行空间大小的修改。判断空间代码如下:

//判断空间是否足够if (ps->top == ps->capacity)//top==capacity说明空间不够{int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//三目操作符STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * newcapacity);if (tmp==NULL)//防止空间申请失败{perror("realloc fail!");return;}ps->a = tmp;ps->capacity = newcapacity;}

        于此段代码之中,有两个非常巧妙之处:1,空间是否足够的判断:让我们仔细想想,当top变量等于capacity变量时是什么情况?

         对,就是如上图所示,当两者相等的时候,也就意味着整个动态数就只有一个空间以供使用了,而这时,我们就需要进行空间的动态开辟了。 

         2,三目操作符的使用:仔细想想,以下两种代码有什么不一样的呢?

代码一:
int newcapacity = ps->capacity * 2;
代码二:
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;

        其实答案十分简单,在我们对栈进行初始化的时候,我们将topcapacity变量都初始化为了0,那如果是代码一0*2就为0,则不就乱套了吗?所以我们便使用代码二用到了三目操作符来避免0*20的尴尬情况

        而之后的入栈函数就十分简单了,但千万别忘了要对top进行++处理!! 

// 入栈 
void StackPush(ST* ps, STDataType data)
{assert(ps);//判断空间是否足够if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * newcapacity);if (tmp==NULL){perror("realloc fail!");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = data;//top处加入新的元素ps->top++;//栈顶的移动
}

4,出栈

        对于出栈函数,其实我们所需要做的就是删除掉栈顶的元素,并且将栈顶向后移动一位。而对于栈顶元素的删除,我们也无需像链表一样使用free函数,我们只需要将top1即可,十分的简单。直接上代码!

// 出栈 
void StackPop(ST* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}

5,取栈顶的数据

        因为栈顶是一个中及其特殊的位置,所以我们也就时不时会用到栈顶的数据,而这个函数就很好的帮我们解决了这个问题。

        在这个函数中,我们唯二需要注意的就是栈不可以为空指针,栈的数据个数不可以为零。代码走起!

// 获取栈顶元素 
STDataType StackTop(ST* ps)
{assert(ps);//栈不为空指针assert(ps->top > 0);//栈的数据个数不能为零STDataType tmp = ps->a[ps->top - 1];//top-1才为栈顶元素的下标return tmp;
}

6,获取栈中数据的个数

        这个函数是关于栈的数据操作函数中最简单的一个函数。栈中的数据个数不就是top的值吗,所以我们直接返回top就可以了。代码如下:

// 获取栈中有效元素个数 
int StackSize(ST* ps)
{assert(ps);return ps->top;
}

7,判断栈是否为空

        该函数比较特殊,它使用到的是布尔类型。如果栈为空,就返回true;反之则返回false。而对于是否为空的判断,我们只需要观察top是否为零就可以了。所以代码如下:

// 检测栈是否为空
bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;//若top为零,则为true;反之则为false
}

四,结语

        这是有关数据结构中的讲解,是不是易如反掌呢?之后我也会接着更新数据结构中另一个知识点——队列的讲解。

        博客不仅是我记录所学习到的知识点的工具,也是我找到同样有学习编程爱好的人的朋友圈,希望我的博客可以对你有所帮助,也希望你可以留下你的鼓励,你的鼓励就是我最大的动力!!加油!

相关文章:

C语言栈的含义与栈数据操作代码详解!

引言&#xff1a;在本篇博客中&#xff0c;我们将学到数据结构——栈&#xff0c;讲到栈的含义与关于栈的数据操作代码。栈可以在顺序表、双向链表以及单链表的基础上实现&#xff0c;而于本篇博客中&#xff0c;我们选择在顺序表的基础上实现栈。 更多有关C语言和数据结构知识…...

数据库基础语法二

一、数据库 1、登陆数据库 2、创建数据库zoo 3、修改数据库zoo字符集为gbk 4、选择当前数据库为zoo 5、查看创建数据库zoo信息 6、删除数据库zoo mysql -uroot -p #登陆数据库 create database zoo; #创建数据库zoo alter database zoo character set gbk collate gbk_…...

数据库的一些知识点

在Sno between列上创建约束,要求Sno的值在18至22岁之间,约束名Sno_CK。请写出对应的完整性命名子句constraint Sno_CK primary key check and。 本题得分&#xff1a; 0分 正确答案&#xff1a; 填空1 : 学号填空2 : snobetween18and22 2.单选题 (12分) 下述SQL命令的短语中…...

[AutoSar]BSW_Com021单帧 首帧 流控帧 连续帧 详解

目录 关键词平台说明一、N_PDU和N_PCI二、单帧三、首帧四、流控帧五、连续帧六、case 关键词 嵌入式、C语言、autosar、OS、BSW、UDS、diagnostic 平台说明 项目ValueOSautosar OSautosar厂商vector &#xff0c; EB芯片厂商TI 英飞凌编程语言C&#xff0c;C编译器HighTec (…...

CSS学习笔记之中级教程(一)

1、CSS 布局 - display 属性 1.1 display 属性 display 属性是用于控制布局的最重要的 CSS 属性。 display 属性规定是否/如何显示元素。 每个 HTML 元素都有一个默认的 display 值&#xff0c;具体取决于它的元素类型。大多数元素的默认 display 值为 block 或 inline。 …...

Spring Cloud Alibaba 网关 Gateway 集成(7)

项目的源码地址 Spring Cloud Alibaba 工程搭建&#xff08;1&#xff09; Spring Cloud Alibaba 工程搭建连接数据库&#xff08;2&#xff09; Spring Cloud Alibaba 集成 nacos 以及整合 Ribbon 与 Feign 实现负载调用&#xff08;3&#xff09; Spring Cloud Alibaba Ribbo…...

低代码技术赋能未来乡村建设:创新与实践

引言 随着我国新型城镇化进程的推进&#xff0c;乡村建设正面临着前所未有的挑战。如何在有限的人力、物力、财力资源下&#xff0c;高效推动乡村建设&#xff0c;实现城乡一体化发展&#xff0c;成为当下亟待解决的问题。低代码技术作为一种创新性的解决方案&#xff0c;为未来…...

基于Springboot的房屋租赁管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的房屋租赁管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…...

跨平台移动应用开发指南:打造跨越iOS和Android的移动应用

跨平台移动应用开发已经成为许多开发者的首选&#xff0c;因为它可以节省时间、成本和精力&#xff0c;同时使得应用能够覆盖更广泛的用户群体。本指南将介绍跨平台移动应用开发的基本概念、流行的跨平台框架以及一些最佳实践&#xff0c;帮助您快速入门并打造出高质量的跨平台…...

QT+多线程编程

QT的多线程编程有两种 1、自定义类继承QThread 第一种是自定义一个类继承于QThread&#xff0c;重写run()方法来实现。然后当需要使用线程的时候你就新建一个自定义对象&#xff0c;然后调用start方法开始运行。 下面的例子是widget里面创建一个线程&#xff0c;然后调用sta…...

设计模式——迭代器模式(Iterator)

迭代器模式&#xff08;Iterator Pattern&#xff09;是一种行为设计模式&#xff0c;它使得我们能够顺序地访问一个聚合对象中的各个元素&#xff0c;而又不需要暴露该对象的内部表示。迭代器模式为遍历不同的聚合结构提供了一个统一的接口&#xff0c;使得客户端代码可以独立…...

在k8s中安装Grafana并对接Prometheus,实现k8s集群监控数据的展示

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Grafana&#xff1a;让数据说话的魔术师》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Grafana简介 2、Grafana的重要性与影响力 …...

【JavaScript】内置对象 - 数组对象 ③ ( 数组反转 - reverse 方法 | 数组排序 - sort 方法 | 自定义数组排序规则 )

文章目录 一、数组排序1、翻转数组元素 - reverse()2、数组元素排序 - sort() 默认从小到大排序3、数组元素排序 - sort() 自定义排序规则4、数组元素排序 - sort() 自定义降序排序简化写法 Array 数组对象参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/JavaScript…...

ctfshow web入门 php反序列化 web267--web270

web267 查看源代码发现这三个页面 然后发现登录页面直接admin/admin登录成功 然后看到了 ///backdoor/shell unserialize(base64_decode($_GET[code]))EXP <?php namespace yii\rest{class IndexAction{public $checkAccess;public $id;public function __construct(){…...

智慧公厕解决什么问题?实现了什么样的价值?

公共厕所一直是城市管理的难题&#xff0c;常常面临着卫生条件不佳、管理不善以及使用体验差等问题。为了解决这些困扰城市的难题&#xff0c;智慧公厕应运而生。智慧公厕不仅应用了信息化和数字化技术&#xff0c;还通过全方位的智能化应用&#xff0c;彻底改变了传统公厕的面…...

IATF16949认证是什么?

IATF16949认证是一项国际质量管理体系的认证标准&#xff0c;由国际汽车行业联合会&#xff08;IATF&#xff09;开发&#xff0c;旨在提高汽车行业的质量管理水平&#xff0c;满足客户对汽车部件和零部件的要求。该标准是在ISO/TS 16949标准的基础上&#xff0c;专门为汽车行业…...

【Vue2】关于response返回数据的错误小记

关于Vue2中response返回数据的一个错误小记 如图&#xff0c;在这里返回的时候&#xff0c;后端是通过List< String >返回的&#xff0c;response接收到的实际上是一个Array数组&#xff0c;但是赋值给searchedTaskList的时候&#xff0c;需要在.then包括的范围里面赋值给…...

深入理解C++构造函数和析构函数

目录标题 1. 构造函数默认构造函数参数化构造函数拷贝构造函数 2. 析构函数3. 构造函数和析构函数的使用场景自动资源管理防止资源泄露深拷贝和浅拷贝 4. C的类中必定有个构造函数吗&#xff1f;5. 总结 C中的构造函数和析构函数是类对象生命周期管理的重要组成部分。构造函数用…...

CMakeLists.txt语法规则:数学运算 math

一. 简介 前面几篇文章学习了 CMakeLists.txt语法中的一些常用变量&#xff0c;常用命令&#xff0c;双引号的作用。条件判断语句&#xff0c;循环语句等等。 本文简单学习一下 CMakeLists.txt语法中数学运算 match。 二. CMakeLists.txt语法规则&#xff1a;数学运算 math 在…...

图片无损压缩工具-VIKY

一、前言 Viky v3.4是一款功能强大的图片压缩工具&#xff0c;它能够提供高效的图片无损压缩服务。通过使用独特的压缩算法&#xff0c;该软件在显著减小图片文件大小的同时&#xff0c;还保持了图像的清晰度和色彩饱和度&#xff0c;确保了图像质量的优异表现。 二、软件特点…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...