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
}

四,结语

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/7780.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用算法汇总

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法篇 &#x1f43e;算法思维逻辑&#x1f43e; 文章目录 1.判断闰年2.计算从某天到某天的天数3.二分4. 前缀和5.差分6.图论6.1dfs6.2走迷宫 7.最短路7.1dijkstra7.2foly 8.并查集9.数论9.1gcd lcm9.2判断素数(质数)9.3分解质因…

Linux设置脚本任意位置执行

记得备份 &#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 修改文件之后记得用 source 文件名 刷新 注意&#xff1a;刷新文件之后在当前窗口…

2024/5/7 QTday2

练习&#xff1a;优化登录框&#xff0c;输入完用户名和密码后&#xff0c;点击登录&#xff0c;判断账户是否为 Admin 密码 为123456&#xff0c;如果判断成功&#xff0c;则输出登录成功&#xff0c;并关闭整个登录界面&#xff0c;如果登录失败&#xff0c;则提示登录失败&a…

[CISCN2019 华北赛区 Day1 Web2]ikun

看到提示说一定要找到lv6 这要写脚本来爆破了&#xff0c;用bp是爆破不出来的 发现LV等级都是有参数挂着的 写个脚本看一下 import requests for i in range(1,1000):payload"http://node4.anna.nssctf.cn:28150/shop?page%d"%(i)resrequests.get(payload)if "…

Misc 流量分析

流量分析简介 网络流量分析是指捕捉网络中流动的数据包&#xff0c;并通过查看包内部数据以及进行相关的协议、流量分析、统计等来发现网络运行过程中出现的问题。 在CTF比赛中&#xff0c;以及各种技能大赛对于流量包的分析取证是一种十分重要的题型。通常这类题目都是会提供…

【工作记录】openjdk-22基础镜像的构建

背景 近期使用到的框架底层都用的是springboot3.0&#xff0c;要求jdk版本在17甚至更高。 于是决定制作一个基于openjdk22的基础镜像&#xff0c;本文对这一过程进行记录。 作为记录的同时也希望能够帮助到需要的朋友。 期望效果 容器内可以正常使用java相关命令且版本是2…

6.移除元素

文章目录 题目简介题目解答解法一&#xff1a;双指针代码&#xff1a;复杂度分析&#xff1a; 解法二&#xff1a;双指针优化代码&#xff1a;复杂度分析&#xff1a; 题目链接 大家好&#xff0c;我是晓星航。今天为大家带来的是 相关的讲解&#xff01;&#x1f600; 题目简…

上海计算机学会2021年1月月赛C++丙组T2康托表

题目背景 康托是一名数学家&#xff0c;他证明了一个重要的定理&#xff0c;需要使用一张表&#xff1a; 这个表的规律是&#xff1a; 从上到下&#xff1a;每一行的分子依次增大&#xff1b;从左到右&#xff1a;每一列的分母依次增大。 康托以一种不重复、不遗漏的方式&am…

基于Springboot的教学辅助系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的教学辅助系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

QSPI的使用

Quad SPI接口(QSPI)是一种同步串行数据链路,在主模式下提供与外部设备的通信。它类似于SPI协议,只是它有额外的数据线。 普通SPI有四条通信线路:芯片选择、时钟、MOSI和MISO。对于QSPI,可提供额外的数据线。因此,命令/数据/地址是根据所选模式通过单、四或双IO发送的。由…

Linux实操之常用指令详解

文章目录 vi 和 vimvi 和 vim 基本使用 开机、重启和用户登录注销关机&重启命令用户登录和注销 用户管理基本介绍基本语法细节说明修改密码删除用户查询用户信息指令切换用户查看当前用户/登录用户用户组 实用指令指定运行级别帮助指令文件目录类时间和日期类搜索查找类压缩…

ENVI下实现遥感矿物蚀变信息提取

蚀变岩石是在热液作用影响下&#xff0c;使矿物成分、化学成分、结构、构造等发生变化的岩石。由于它们经常见于热液矿床的周围&#xff0c;因此被称为蚀变围岩&#xff0c;蚀变围岩是一种重要的找矿标志。利用围岩蚀变现象作为找矿标志已有数百年历史&#xff0c;发现的大型金…

Linux\_c输出

第一条Linux_c输出 初界面 : ls # 显示目录下的文件cd # 进入到某个目录 # 比如 我进入了Codels # 发现没有显示, 说明为文件下为空vim cpucdoe.c # 创建一个 .c的源码文件进入到了vim的编辑界面: i # 按i 就可以进行编辑 , 下面显示插入标识在编辑模式下, 可以通…

Java性能优化(五)-多线程调优-Lock同步锁的优化

作者主页&#xff1a; &#x1f517;进朱者赤的博客 精选专栏&#xff1a;&#x1f517;经典算法 作者简介&#xff1a;阿里非典型程序员一枚 &#xff0c;记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法&#xff08;公众号同名&#xff09; ❤️觉得文章还…

Android getevent命令详细分析

在调试Android 的输入事件时&#xff0c;经常使用 “getevent -lrt” 命令&#xff0c;来确认驱动上报数据是否正常。从源码的角度来详细的分析一下getevent 这个程序。 首先用ls命令来看一下getevent lrwxr-xr-x 1 root shell 7 2023-11-20 10:08 system/bin/getevent -> …

独有病眼花,春风吹不落。 (二维坐标压缩成一个点,并查集)

本题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 题目&#xff1a; 样例&#xff1a; 输入 3 8 1 1 D 1 1 R 1 2 D 2 1 D 2 2 R 3 1 R 3 2 R 2 3 D 输出 8 思路&#xff1a; 根据题意&#xff0c;要求连接线段后&#xff0c;操作多少次&#xff0c;连接的线段闭合&…

cmake install命令无法覆盖同名文件

文章目录 1. 问题记录2. 原因排查3. 解决方案 1. 问题记录 我有两个同名文件test.txt&#xff0c;它们内容不同&#xff0c;但时间戳相同&#xff08;文件属性中的修改时间相同&#xff09; 我希望在cmake中利用install命令&#xff0c;将${PATH_SRC}/test.txt替换${PATH_DES…

智能网联汽车网络和数据安全态势分析

文章目录 前言一、我国智能网联汽车安全态势分析(一)我国高度重视智能网联汽车安全发展(二)产业高速发展伴随网络安全隐患(三)网络和数据安全风险事件威胁加剧二、智能网联汽车网络和数据安全典型实践剖析(一)立标准规范,把牢安全发展“方向盘”(二)强车主服务,系好…

数据库系统理论——绪论

文章目录 前言一、数据库四个基本概念1、数据2、数据库3、数据库管理系统&#xff08;DBMS&#xff09;4、数据库系统&#xff08;DBS&#xff09; 二、数据模型1、概念数据模型2、逻辑数据模型3、物理数据模型 三、三级模式1、图片解析2、二级映像 前言 最近很长时间没更新学…

上海个人购房提取公积金经历和注意事项(收藏不踩坑)

在前一篇文章中&#xff0c;我介绍了 2024 年 4 月 24 日上海个人购房个税退税经历&#xff0c;我于 4 月 27 日周六&#xff0c;顺利办理租房公积金提取业务&#xff0c;资金在业务办理完成后 10 分钟左右到账。通过本文分享办理过程的材料和注意事项&#xff0c;避免大家踩坑…