嵌入式初学-C语言-数据结构--四
栈
1. 基本概念
栈是一种逻辑结构,是特殊的线性表。特殊在:
只能在固定的一端操作
只要满足上述条件,那么这种特殊的线性表就会呈现一种“后进先出”的逻辑,这种逻辑就被称为栈。栈 在生活中到处可见,比如堆叠的盘子、电梯中的人们、嵌套函数的参数等等。

由于约定了只能在线性表固定的一端进行操作,于是给栈这种特殊的线性表的“插入”、“删除”,另起了 下面这些特定的名称:
栈顶:可以进行插入删除的一端
栈底:栈顶的对端
入栈:将节点插入栈顶之上,也称为压栈,函数名通常为push()
出栈:将节点从栈顶剔除,也称为弹栈,函数名通常为pop()
取栈顶:取得栈顶元素,但不出栈,函数名通常为top()
基于这种固定一端操作的简单约定,栈获得了“后进先出”的基本特性,如下图所示,最后一个放入的元 素,最先被拿出来:
2. 存储形式
栈只是一种数据逻辑,如何将数据存储于内存则是另一回事。一般而言,可以采用顺序存储形成顺序 栈,或采用链式存储形成链式栈。
顺序栈 顺序存储意味着开辟一块连续的内存来存储数据节点,一般而言,管理栈数据除了需要一块连续的 内存之外,还需要记录栈的总容量、当前栈的元素个数、当前栈顶元素位置,如果有多线程还需要 配互斥锁和信号量等信息,为了便于管理,通常将这些信息统一于在一个管理结构体之中:
// 顺序栈节点
struct seqStack
{
datatype *data; // 顺序栈入口
int size; // 顺序栈总容量
int top; // 顺序栈栈顶元素下标
};

链式栈
链式栈的组织形式与链表无异,只不过插入删除被约束在固定的一端。为了便于操作,通常也会创 建所谓管理结构体,用来存储栈顶指针、栈元素个数等信息:
// 链式栈节点
typedef struct node
{
datatype data;
struct node *next;
}node;
// 链式栈管理结构体
struct linkStack
{
node *top; // 链式栈栈顶指针
int size; // 链式栈当前元素个数
};

3. 基本操作
不管是顺序栈,链式栈,栈的操作逻辑都是一样的,但由于存储形式不同,代码的实现是不同的。下 面分别将顺序栈和链式栈的基本核心操作罗列出来:
顺序栈
sstack.h
#ifndef __SSTACK_H
#define __SSTACK_H
// 数据类型
typedef int DATA;
// 顺序栈结构体
typedef struct
{
DATA *pData; // 栈中元素的地址
int size; // 栈的总容量
int top; // 栈顶元素下标
}SeqStack;
// 初始化栈
int SStack_init(SeqStack *s, int num);
// 判断栈是否已满
int SStack_isfull(SeqStack *st);
// 判断栈是否为空
int SStack_isempty(SeqStack *st);
// 入栈/压栈
int SStack_push(SeqStack *st,DATA data);
// 出栈/弹栈
int SStack_pop(SeqStack *st,DATA *data);
// 回收栈
int SStack_free(SeqStack *st);
#endif
sstack.c
#include <stdlib.h>
#include "sstack.h"
// 初始化栈
int SStack_init(SeqStack* s,int num)
{
s -> pData = (DATA*)calloc(sizeof(DATA),num);
if(s -> pData == NULL)
return -1;
s -> size = num ;
s -> top = -1;
return 0;
}
// 判断栈是否已满
int SStack_isfull(SeqStack *st)
{
return st -> top + 1 == st -> size;
}
// 判断栈是否为空
int SStack_isempty(SeqStack *st)
{
return st -> top == -1;
}
// 压栈/入栈
int SStack_push(SeqStack *st,DATA data)
{
if(SStack_isfull(st))
return -1;
st -> top++;
st -> pData[st -> top] = data;
return 0;
}
// 出栈/弹栈
int SStack_pop(SeqStack *st,DATA *data)
{
if(SStack_isempty(st))
return -1;
*data = st -> pData[st -> top];
st -> top--;
return 0;
}
// 回收栈
int SStack_free(SeqStack *st)
{
if(st -> pData)
{
free(st->pData);
st -> pData = NULL;
}
st -> top = -1;
}
sstack_main.c
#include "sstack.h"
#include <stdio.h>
int main(void)
{
SeqStack st;
SStack_init(&st,10);
register int i = 1;
for(; i <=10; i++)
SStack_push(&st,i);
if(-1 == SStack_push(&st,1024))
fprintf(stderr,"满栈,插入失败\n");
while(!SStack_isempty(&st))
{
DATA data = 0;
SStack_pop(&st,&data);
printf("%4d",data);
}
printf("\n");
SStack_free(&st);
return 0;
}
链式栈
inkstack.h
#ifndef __LINKSTACK_H
#define __LINKSTACK_H
// 数据类型
typedef int DATA;
// 链式栈节点
typedef struct _node
{
DATA data; // 数据
struct _node *next; // 指向下一个栈的节点
}NODE;
// 链式栈管理结构体
typedef struct
{
NODE *pHead;// 链式栈栈顶指针
int size; // 链式栈当前元素个数
int num;
}LinkStack;
// 初始化链式栈
int LStack_init(LinkStack *s, int num);
// 判断栈是否已满
int LStack_isfull(LinkStack *st);
// 判断栈是否为空
int LStack_isempty(LinkStack *st);
// 压栈/入栈
int LStack_push(LinkStack *st,DATA data);
// 弹栈/出栈
int LStack_pop(LinkStack *st,DATA *data);
// 回收栈
int LStack_free(LinkStack *st);
#endif
linkstack.c
#include "linkstack.h"
#include <stdio.h>
#include <stdlib.h>
// 初始化栈
int LStack_init(LinkStack *st, int num)
{
st -> pHead = NULL;
st -> size = num;
st -> num = 0;
return 0 ;
}
// 判断栈是否已满
int LStack_isfull(LinkStack *st)
{
return st -> num == st -> size;
}
// 判断栈是否为空
int LStack_isempty(LinkStack *st)
{
return st -> num == 0;
}
// 入栈
int LStack_push(LinkStack *st,DATA data)
{
if(LStack_isfull(st))
return -1;
NODE* p = (NODE*)malloc(sizeof(NODE));
if(!p)
return -1;
p -> data = data;
p -> next = st -> pHead;
st -> pHead = p;
(st -> num)++;
return 0;
}
// 出栈
int LStack_pop(LinkStack *st,DATA *data)
{
if(LStack_isempty(st))
return -1;
NODE* p = st -> pHead;
if(!p)
return -1;
*data = p -> data;
st -> pHead = p -> next;
free(p);
(st -> num)--;
return 0;
}
// 回收栈
int LStack_free(LinkStack *st)
{
NODE* p = st -> pHead, *q = NULL;
while(p)
{
q = p;
p = p -> next;
free(q);
}
st -> pHead = NULL;
st -> num = 0;
return 0;
}
linkstack_main.c
#include "linkstack.h"
#include <stdio.h>
int main(void)
{
LinkStack st;
LStack_init(&st,10);
register int i = 1;
for(; i <= 10; i++)
LStack_push(&st,i);
if(-1 == LStack_push(&st,1024))
fprintf(stderr,"满栈,插入失败\n");
while(!LStack_isempty(&st))
{
DATA data = 0;
LStack_pop(&st,&data);
printf("%4d",data);
}
printf("\n");
LStack_free(&st);
return 0;
}
使用链式栈,实现十进制转八进制:键盘输入一个十进制数,经过链式栈的相关算法,输出八进制 数。

相关文章:
嵌入式初学-C语言-数据结构--四
栈 1. 基本概念 栈是一种逻辑结构,是特殊的线性表。特殊在: 只能在固定的一端操作 只要满足上述条件,那么这种特殊的线性表就会呈现一种“后进先出”的逻辑,这种逻辑就被称为栈。栈 在生活中到处可见,比如堆叠的盘子…...
【HarmonyOS 4】应用性能优化
1. ArkTs 高性能编程 1.1 ArkTs 高性能编程规则 1.1.1 限制一些 TypeScript 的特性,比如需要不支持属性的动态变更、变量或参数需要明确的类型声明和返回值声明等。1.1.2 禁用 ts-ignore、ts-expect-error 等屏蔽编译校验的命令。1.1.3 开启 TypeScript 的严格模式…...
MySQL——表操作
目录 一、创建表 二、查看表 2.1 查看表中某成员的数据 2.2 查看整个表中的表成员 2.3 查看创建表时的句柄 三、修改表 alter 3.1 重命名 rename 3.2 新增一列 add 3.3 更改列属性 modify 3.4 更改列名称 change 3.5 删除某列 上一篇博客介绍了库的操作,…...
阅读笔记--Guiding Attention in End-to-End Driving Models(二)
端到端驾驶的注意力学习(Attention Learning for End-to-End Driving)关键内容学习 3.1 问题设置(Problem Setup) 模仿学习(Imitation Learning, IL):介绍了模仿学习的概念,即通过…...
Linux: network: TCP: errno: EWOULDBLOCK
https://mzhan017.blog.csdn.net/article/details/108010013 这个errno的意思: 如果是send接口函数返回的错误,代表tcp socket的sending buffer满了,让应用程序等上一段时间重试send。 所以,这个产生的原因就不固定了: 可能是当前系统太忙,导致系统发包慢,buffer累积; 可…...
闲话“设计模式”
Q1、请详细介绍 软件架构设计模式(智能化),应用程序设计模式(自动化),编程语言设计模式(人性化)(后面括号中 是我 希望 其 具有的特点) 的概念,有…...
Sentence-BERT实现文本匹配【CoSENT损失】
引言 还是基于Sentence-BERT架构,或者说Bi-Encoder架构,但是本文使用的是苏神提出的CoSENT损失函数1。 点击来都是缘分,之前过时的方法可以不细看,别的文章可以不收藏,现在是最流行的方法,这篇文章建议收藏…...
业余考什么证书比较实用?
在业余时间里,获得一些有用的证书不仅能提升你的专业素养,还能增强你在职场上的竞争力。 特别是职业技能证书和行业认证证书,这两者受到了广大职场人士的高度关注。 一、业余时间考取的实用证书 行业认证证书主要针对特定行业或职业&#…...
16款facebook辅助工具,总有一款适合你!
Hey小伙伴们~👋 是不是想利用FB大展拳脚,却苦于不知道如何开始?别急,今天就给你们安利16个超实用的FB营销工具,涵盖了内容创建和发布的应用程序,以及数据追踪分析、商品销售等多个方面让你轻松get海外获客新…...
给网站发外链的好处,你了解多少?
在当今这个信息爆炸的互联网时代,网站优化和推广成为了每一个网站主不可忽视的重要环节。其中,给网站发外链,即在其他网站上设置指向自己网站的链接,是一种高效且被广泛采用的策略。那么,给网站发外链究竟能带来哪些好…...
安卓链接正常显示,ios#符被转义%23导致链接访问404
原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理 如下: guard let allowUrl webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时&a…...
excel分列
Excel中有这么几列,希望将每一列内容再分出3列: 可以通过以下步骤在 Excel 表格中将 B 到 F 列的内容拆分为每列的 3 列,分别为 pred_label、pred_score 和 pred_class: 确定数据结构:假设 B 列到 F 列中的内容都是按类…...
STM32 HAL DMA 中断碰到的问题
流程 串口收数据—>dma搬运到变量—>空闲中断----->接收完成 配置 dma中断全部去掉 串口中断开启 freertos中断全部去掉 时钟配置 代码 开启中断 // DMA 空闲检查 void receives_uaru_7(void) {RXU7 0;//清除中断标志HAL_UARTEx_ReceiveToIdle_DMA(&hua…...
让树莓派智能语音助手实现定时提醒功能
最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束…...
AIoTedge边缘计算+边缘物联网平台
在数字化转型的浪潮中,AIoTedge边缘计算平台以其边云协同的架构和强大的分布式AIoT处理能力,正成为推动智能技术发展的关键力量。AIoTedge通过在数据源附近处理信息,实现低延迟、快速响应,增强了应用的实时性。同时,它…...
Java使用拷贝asset文件,解密,并用DexclassLoader加载执行
//asset中加密的apk文件重命名为index.html,拷贝到私有目录 //解密 //加载,执行apk中的方法 public static void handleByJava(Context context){File copyedFile new File(context.getFilesDir().getAbsolutePath() "/" "main.html");FileUtil.copyAss…...
【AcWing】861. 二分图的最大匹配(匈牙利算法)
匈牙利算法,他可以在比较快的时间复杂度之内告诉我们左边和右边成功匹配的最大数是多少 匹配指的是边的数量,成功的匹配指的是两个未被使用的点之间存在一条边(就不存在两条边共用了一个点的)。 匈牙利算法可以返回成功匹配的最大匹配数是多少。 #incl…...
经验笔记:JSP(JavaServer Pages)
JSP(JavaServer Pages)经验笔记 JSP(JavaServer Pages)是一种用于创建动态网页的技术,它允许在HTML页面中嵌入Java代码,从而实现动态内容的生成。JSP与Servlet一样,都是Java EE平台的一部分&am…...
【零基础必看的数据库教程】——SQL WHERE 子句
WHERE 子句用于提取那些满足指定条件的记录,过滤记录。 SQL WHERE 语法: SELECT column1, column2, ... FROM table_name WHERE condition; 参数说明: column1, column2, ...:要选择的字段名称,可以为多个字段。如…...
vscode docker debug python
1. 安装Vscode插件 ”Docker“”Dev Containers““Remote - ssh” 2. 进入Docker环境 点击左侧 Docker图标,选择Containers 对容器进行右键启动 生成新页面直接进行选择文件路径即可,之后得操作均在容器内进行...
行列式点过程:从统计独立到负依赖的机器学习范式跃迁
1. 项目概述:从统计独立到负依赖的范式跃迁在机器学习和统计学的工具箱里,统计独立性长期以来扮演着基石的角色。从朴素贝叶斯分类器的特征条件独立假设,到蒙特卡洛方法中独立同分布的采样点,再到随机梯度下降中独立的小批量数据&…...
教师今晚必须做的1件事:用Claude 3.5 Sonnet重写你的公开课逐字稿——实测课堂语言感染力提升58%(附对比音频+评分报告)
更多请点击: https://codechina.net 第一章:Claude 3.5 Sonnet在教育内容创作中的范式跃迁 传统教育内容生产长期受限于人力密集、周期冗长与个性化不足三大瓶颈。Claude 3.5 Sonnet凭借其增强的推理深度、100K上下文窗口及显著优化的指令遵循能力&…...
差分隐私矩阵机制与FFT优化:保护多轮迭代计算的高效方法
1. 差分隐私矩阵分解:从理论到工程实践在联邦学习、推荐系统这些需要频繁进行多轮迭代计算的场景里,我们常常面临一个核心矛盾:既要利用全体参与者的数据来训练一个高质量的全局模型,又要确保任何单个参与者的敏感信息不会在训练过…...
CentOS7最小化安装后,这3个必做的配置(换源、设静态IP、更新)一个都不能少
CentOS7最小化安装后的三大关键配置实战指南刚完成CentOS 7最小化安装的系统就像毛坯房——虽然基础框架已经就位,但距离真正"拎包入住"还有一段距离。作为运维人员,我们最迫切的需求是快速搭建一个稳定、高效的基础服务器环境。本文将聚焦三个…...
08-系统技术架构师必备——分布式系统理论与数据一致性
关键词:分布式系统、CAP定理、BASE理论、Paxos、Raft、分布式事务、TCC、Saga、一致性算法 分布式系统 CAP定理 分布式事务 一致性算法 Paxos Raft TCC Saga 系统技术架构师必备——分布式系统理论与数据一致性 摘要 分布式系统是系统技术架构师必须跨越的"分水岭"…...
Harness的配置漂移检测与自动修复
云原生时代的稳定性利器:Harness配置漂移检测与自动修复全指南 引言 痛点引入 相信每一位DevOps工程师、SRE或者运维负责人都遇到过这样的噩梦: 测试环境验证了3天的功能,上线到生产10分钟就出现503错误,排查了2小时才发现&…...
SpringBoot+Vue旅游管理系统源码+论文
代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹 分享万套开题报告任务书答辩PPT模板 作者完整代码目录供你选择: 《SpringBoot网站项目》1800套 《SSM网站项目》1500套 《小程序项目》1600套 《APP项目》1500套 《Python网站项目》…...
CANN NPU 功耗优化:推理服务的能效比提升实战
功耗直接影响部署成本和设备寿命。同样的推理任务,功耗优化后能省 30% 电费,设备温度降低 10C。本文讲解 NPU 功耗的来源、动态调频策略、算子级功耗控制,以及在 CANN 上实现绿色推理的实战方法。一、NPU 功耗从哪来 1.1 功耗的三个来源 计算…...
AI检测率太高论文过不了?这4个降AI率平台2026年别再错过了
随着AI技术在学术领域的广泛应用,论文中的AI痕迹越来越容易被检测系统识别。如何有效降低AIGC率、去除AI痕迹,已成为众多学者和学生关注的焦点。依托权威检测平台数据、高校实测结果及用户真实反馈,本文将深入解析当前最值得尝试的降AI率工具…...
AssetStudio深度解析:Unity序列化协议与产线级资源解包实战
1. 这不是“又一个AssetStudio教程”,而是我用它救回三个项目的真实记录AssetStudio、Unity资源提取、AssetBundle解包——这几个词,对做过Unity客户端开发、逆向分析、MOD制作或老游戏复刻的人来说,不是工具名,是救命稻草。我第一…...
