【C语言】栈的实现(数据结构)
前言:
还是举一个生活中的例子,大家都玩过积木,当我们把积木叠起来的时候,如果要拿到最底部的积木,我们必须从顶端一个一个打出,最后才能拿到底部的积木,也就是后进先出(先进后出)的道理,今天分享栈的实现的本质也就是后进先出(先进后出)。
目录
前言:
栈的概念及结构
栈的实现
栈的结构定义
初始化栈
压栈(数据的添加)
出栈(数据的删除)
获取栈顶元素
获取栈中有效元素个数
判断栈是否为空
栈实现的总代码(vs2022)
头文件Stack.h
函数文件Stack.c
测试Text.c
栈的概念及结构
要去实现栈,我们要知道什么是 栈,栈的结构是什么,该从什么方向去实现。

如图我们会发现数据进栈出栈后的顺序倒置了,其实栈不只是可以将顺序导致,我们也可以先把A,B放进去,拿出来之后,再将C,D放进去,全部拿出来可以得到C,D,A,B,所以栈最后导致的结果是多种多样的,这取决你如何运用栈了。
栈的实现
栈的结构定义
typedef int STDataType;typedef struct Stack
{ STDataType* a;int top; //栈顶int capacity;//栈容量
}Stack;
栈只需要对栈顶进行操作,所以我们有一个变量top表示栈顶。后面需要判断栈是否为空,我们需要一个变量capacity表示栈容量。
初始化栈
void StackInit(Stack* ps)
{assert(ps);ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);ps->top = 0;ps->capacity = 4;
}
这里我们创造了4个整型变量的空间,所以capacity给4。
压栈(数据的添加)
void StackPush(Stack* ps,STDataType x)
{assert(ps);if (ps->top == ps->capacity)//考虑到空间大小不够,使用realloc进行增容操作{STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));if (tmp == NULL)//要注意tmp可能为空的情况。{printf("realloc fail!!!");exit(-1);}ps->a = tmp;//别忘了把指针a指向新开辟的空间ps->capacity *= 2;}ps->a[ps->top] = x;ps->top++;//注意个数的增加
}
在压栈的时候要注意几点:
1.压栈时要考虑空间的大小是否足够,不够时要进行增容操作。
2.增容操作后的原指针要指向新指针,保证数据不会丢失。
3.压栈过后要对将top往后移动一位,因为top的指向是数组最后元素的下一个位置。
出栈(数据的删除)
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);//top不能小于或等于0,因为top是指向栈顶元素的下一个位置ps->top--;
}
因为是用数组进行栈的实现,我们只需要把栈顶往前移动一位,就表示删除了数据。
获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];//因为top是指向栈顶元素的下一个位置,所以要-1}
一定注意对ps->top>0进行断言,保证栈的元素不为空。
获取栈中有效元素个数
int StackSize(Stack* ps)
{assert(ps);return ps->top;}
top指向的数组尾部元素后一位,刚好是数组中有效元素的个数。
判断栈是否为空
bool StackEmpty(Stack* ps)//bool也可以使用 表示真假
{assert(ps);return ps->top == 0;
}
检查栈是否为空,如果不为空则返回0,如果为空则返回非零结果。
栈实现的总代码(vs2022)
头文件Stack.h
#pragma once#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>
typedef int STDataType;typedef struct Stack
{ STDataType* a;int top; //栈顶int capacity;//栈容量
}Stack;
//初始化栈
void StackInit(Stack* ps);
//栈的销毁
void StackDestory(Stack* ps);
//压栈
void StackPush(Stack* ps,STDataType x);
//出栈
void StackPop(Stack* ps);
//获取栈顶元素
STDataType StackTop(Stack* ps);
//获取栈中有效元素的个数
int StackSize(Stack* ps);
//检查栈是否为空,如果不为空则返回0,如果为空则返回非零结果
bool StackEmpty(Stack* ps);//bool也可以使用 表示真假
函数文件Stack.c
#include"Stack.h"void StackInit(Stack* ps)
{assert(ps);ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);ps->top = 0;ps->capacity = 4;
}
void StackDestory(Stack* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;}
//入栈
void StackPush(Stack* ps,STDataType x)
{assert(ps);if (ps->top == ps->capacity)//考虑到空间大小不够,使用realloc进行增容操作{STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));if (tmp == NULL)//要注意tmp可能为空的情况。{printf("realloc fail!!!");exit(-1);}ps->a = tmp;//别忘了把指针a指向新开辟的空间ps->capacity *= 2;}ps->a[ps->top] = x;ps->top++;//注意个数的增加
}
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);//top不能小于或等于0,因为top是指向栈顶元素的下一个位置ps->top--;
}
STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];//因为top是指向栈顶元素的下一个位置,所以要-1}
int StackSize(Stack* ps)
{assert(ps);return ps->top;}
bool StackEmpty(Stack* ps)//bool也可以使用 表示真假
{assert(ps);return ps->top == 0;
}
测试Text.c
#include"Stack.h"void StackText()
{Stack st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPush(&st, 5);while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}StackDestory(&st);
}int main()
{StackText();return 0;
}
好啦,这就是今天学习的分享啦!看到希望大家的三连呀!
如果有不当之处,欢迎大佬指正!
相关文章:

【C语言】栈的实现(数据结构)
前言: 还是举一个生活中的例子,大家都玩过积木,当我们把积木叠起来的时候,如果要拿到最底部的积木,我们必须从顶端一个一个打出,最后才能拿到底部的积木,也就是后进先出(先进后出&a…...

前端三大主流框架对比
在现代前端开发中,React、Vue和Angular是三大流行的框架/库。它们各自有独特的优缺点,适用于不同的开发需求和项目规模。下面是对这三者的详细比较: 一、 React 简介: 由Facebook开发和维护,是一个用于构建用户界面…...

AOP~面向切面编程介绍
AOP基础 概述 AOP:Aspect Oriented Programming(面向切面编程、面向方面编程),面向特定方法的编程。 动态代理是面向切面编程最主流的实现。 SpringAOP是Spring框架的高级技术,旨在管理bean对象的过程中,…...
Android SurfaceFlinger——GraphicBuffer的提交(三十三)
在 SurfaceFlinger 中,我们 dequeueBuffer 和 queueBuffer 是 Surface 控制接口中非常重要的两个函数,分别用于从 Surface 的 BufferQueue 中取出缓冲区和向 BufferQueue 提交(队列)缓冲区。这两个函数在生产者和消费者模型中扮演着核心角色,确保了图像数据的高效和有序传…...

创维汽车滁州永通体验中心开业仪式暨超充车型区域上市会圆满成功
2024年7月20日,创维汽车滁州永通体验中心盛大开业,当日,创维汽车市场部经理周世鹏、安徽大区总监王大明等领导参加本次开业盛典,共同见证创维汽车滁州永通体验中心成功落地。 2021年,新能源乘用车高速发展,…...

【PHP】系统的登录和注册
一、为什么要学习系统的登录和注册 系统的登录和注册可能存在多种漏洞,这些漏洞可能被恶意攻击者利用,从而对用户的安全和隐私构成威胁。通过学习系统的登录和注册理解整个登录和注册的逻辑方便后续更好站在开发的角度思考问题发现漏洞。以下是一些常见…...
2024.7.29 刷题总结
2024.7.29 **每日一题** 682.棒球比赛,这道题是一道简单的模拟题,用栈模拟题中的四个操作就可以了,操作一是将x加到列表末尾,操作二是将列表的后两项之和加到列表末尾,操作三是把列表最后一项的两倍加到列表末尾&#…...

WebSocket程序设计
协议说明 WebSocket 是一种在单个TCP连接上进行全双工通信的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。Websocket主要用在B/S架构的应用程序中,在 WebSocket API 中,浏览器和服务器只…...

ES(ElasticSearch)倒排索引
目录 正排与倒排索引 1.正排索引 作用: 优点: 缺点: 2.倒排索引 原理: 倒排索引的构建流程: 倒排索引的搜索流程: 优点: 缺点: 3. 应用场景 倒排索引中有几个非常重要的概念…...

Android Studio Build窗口出现中文乱码问题
刚安装成功的android studio软件打开工程,编译时下方build窗口中中文是乱码。 解决: 可点击studio状态栏的Help—>Edit Custom VM Options ,在打开的studio64.exe.vmoptions文件后面添加:(要注意不能有空格,否则st…...
java生成随机数
代码 startValue 开始值 endValue 结束值 per生成的位数也就是精度 /*** 随机数的生成* param startValue* param endValue* return*/private BigDecimal randomBigDecimal(String startValue, String endValue,int per) {BigDecimal min new BigDecimal(startValue);BigDeci…...
动态定制深度学习:Mojo模型与自定义训练算法的无缝切换
动态定制深度学习:Mojo模型与自定义训练算法的无缝切换 引言 在机器学习领域,算法的选择对模型的性能有着决定性的影响。随着研究的深入和技术的发展,开发者可能需要根据不同的数据特性和业务需求,动态地切换或自定义训练算法。…...

昇思25天学习打卡营第19天|DCGAN生成漫画头像
DCGAN生成漫画头像总结 实验概述 本实验旨在利用深度卷积生成对抗网络(DCGAN)生成动漫头像,通过设置网络、优化器以及损失函数,使用MindSpore进行实现。 实验目的 学习和掌握DCGAN的基本原理和应用。熟悉使用MindSpore进行图像…...
排序题目:按照频率将数组升序排序
文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题:按照频率将数组升序排序 出处:1636. 按照频率将数组升序排序 难度 3 级 题目描述 要求 给定一个整数数组 nums \texttt{nums} nums&a…...
实分析与测度论问题的分类
实分析主要研究实数、实数序列、实数极限以及实值函数的分析,而度量空间则是一个具有距离函数的集合,其分类可以从多个角度进行。 实分析 实分析主要关注实数、实数序列、实数极限以及实值函数的分析。它涉及到多个重要的概念和理论,包括但…...

动态代理更改Java方法的返回参数(可用于优化feign调用后R对象的统一处理)
动态代理更改Java方法的返回参数(可用于优化feign调用后R对象的统一处理) 需求原始解决方案优化后方案1.首先创建AfterInterface.java2.创建InvocationHandler处理代理方法3. 调用 实际运行场景拓展 需求 某些场景,调用别人的方法࿰…...

Redis缓存数据库进阶——Redis与分布式锁(6)
分布式锁简介 1. 什么是分布式锁 分布式锁是一种在分布式系统环境下,通过多个节点对共享资源进行访问控制的一种同步机制。它的主要目的是防止多个节点同时操作同一份数据,从而避免数据的不一致性。 线程锁: 也被称为互斥锁(Mu…...
网络芯片(又称为PHY网络芯片)
Realtek RTL8152B是一种常见的主板集成网络芯片(又称为PHY网络芯片)。PHY芯片是指将网络控制芯片的运算部分交由处理器或南桥芯片处理,以简化线路设计,从而降低成本。 https://www.realtek.com/Download/List?cate_id585 Realt…...

01 Go Web基础_20240728 课程笔记
概述 如果您没有Golang的基础,应该学习如下前置课程。 基础不好的同学每节课的代码最好配合视频进行阅读和学习,如果基础比较扎实,则阅读本教程巩固一下相关知识点即可,遇到不会的知识点再看视频。 视频课程 最近发现越来越多…...

嵌入式学习Day12---C语言提升
目录 一、指针数组 1.1.什么是指针数组 2.2. 格式 2.3.存储 2.4.与字符型二维数组相比 2.5.什么时候使用指针数组 2.6.练习 二、数组指针 2.1.什么是数组指针 2.2.格式 2.3.一维数组 2.3.特点 2.4.什么时候使用 三、指针和数组的关系 3.1.一维数组和指针 …...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...

ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...