尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
行到水穷处,坐看栈起时——动态内存的链式之美
引言在数据结构的浩瀚海洋中“栈”Stack作为一种后进先出LIFO, Last In First Out的线性表其重要性不言而喻。此前我们深入探讨过顺序栈的实现与优劣也剖析过单链表、双向链表以及循环链表的 intricacies复杂性。今天我们将这两大基石结合聚焦于一种既具备栈的逻辑特性又拥有链表动态内存优势的数据结构——链栈Linked Stack。一、链栈的认识1.1什么是链栈链栈本质上是一个只允许在表头进行插入和删除的单链表。我们用一个头指针top来标识栈顶(单链表的头节点)入栈push等价于在链表头部插入一个新节点头插出栈pop等价于删除头节点头删。由于操作仅限于头部时间复杂度均为 O(1)。1.2节点与管理结构体的设计指针的艺术链栈节点的设计与链表无异结构体中包括数据域存放数据指针域存放下一个节点的地址//每一个节点的结构体 typedef struct StackNode { ElemType data; //数据域 struct StackNode* next; //指针域 }StackNode, * PstackNode;管理链栈的结构体为了便于管理我们定义一个包含“栈顶指针”和“当前元素个数”的结构体这比单纯使用一个全局头指针更具封装性。​ //管理每一个节点的结构体 typedef struct LinkStack { StackNode* top; //栈顶指针管理链表 (保存链表的头部) size_t cursize; //当前容量 }LinkStack, * PLinkStack; ​补充结构体指针的重命名①先定义结构体再为它的指针类型起别名//先定义一个结构体 struct Student { int id; char name[10]; }; //该结构体的指针为struct Student* //使用重命名的关键字typedef 给指针重命名 typedef struct Student* PStudent; PStudent ps; //使用时可直接用PStudent 代替 struct Student*②在定义结构体时直接重命名最常用//直接给结构体指针重命名 typedef struct Student { int id; char name[10]; } * PStudent; //注意这里的 *直接为指针类型起别名 //或者同时为结构体和指针起别名 typedef struct Student { int id; char name[10]; } Student, * PStudent; //使用 Student s; // 等价于 struct Student s; PStudent ps; // 等价于 struct Student* ps;③匿名结构体的指针重命名typedef struct { int x; int y; } *PointPtr; PointPtr p; // 直接使用1.3链栈示意图这里简单显示了链栈的样子以及出栈及入栈的情形帮助读者理解。二、核心函数的实现C语言购买节点初始化获取元素个数判空入栈打印出栈并获取栈顶元素获取栈顶元素清空销毁2.1购买节点、初始化PstackNode BuyNode(ElemType val) //购买节点void InitLinkStack(PLinkStack ps) //初始化购买节点在进行数据入栈时肯定要重新申请一个节点空间将数据存入节点在将节点进行插入。所以我们将这一重复的步骤包装成函数便于使用初始化对链栈进行初始化//1.购买新节点 PstackNode BuyNode(ElemType val) { PstackNode p (PstackNode)malloc(sizeof(StackNode)); //申请一个节点大小的空间 if (p NULL)return NULL; p-data val; //存入数据 p-next NULL; //先置空指针 return p; } //2.初始化(带头节点) void InitLinkStack(PLinkStack ps) { assert(ps ! NULL); PstackNode p BuyNode(0); //头节点 if (p NULL)return; ps-cursize 0; //链栈容量置为0 ps-top p; //栈顶指针始终指向头节点的地址 }2.2获取元素个数、判空size_t Get_Size(const PLinkStack ps) //获取元素个数bool IsEmpty(const PLinkStack ps) //判空获取元素个数直接返回链栈中的有效元素个数即可return ps-cursize.判空链栈的元素个数为0即为空return ps-cursize 0​ //1.获取元素的个数 size_t Get_Size(const PLinkStack ps) { assert(ps ! NULL); return ps-cursize; } //2.判空 bool IsEmpty(const PLinkStack ps) { assert(ps ! NULL); return ps-cursize 0; } ​2.3入栈、打印bool Push(PLinkStack ps, ElemType val) //入栈void PrintStack(const PLinkStack ps) //打印入栈 链栈的入栈操作等同于单链表的头插法。这是最高效的操作无需遍历链表头插法这里便不过多赘述了打印重新定义一个节点指针从第一个有效节点开始循环遍历每一个节点p p-next输出其中的数据//1.入栈 bool Push(PLinkStack ps, ElemType val) { assert(ps ! NULL); PstackNode p BuyNode(val); //购买新节点 if (p NULL)return false; p-next ps-top-next; //头插让p的指针域保存头节点的指针域 // NULL或者是原第一个有效节点的地址 ps-top-next p; //让头节点的指针域指向p连接完成 ps-cursize; //容量加一 return true; } //2.打印 void PrintStack(const PLinkStack ps) { assert(ps ! NULL); for (PstackNode p ps-top-next; p ! NULL; p p-next) { //p从第一个有效节点开始 printf(%hhd , p-data); //循环终止条件p!NULL } printf(\n); }函数测试2.4出栈并获取栈顶元素、获取栈顶元素bool Pop(PLinkStack ps, ElemType* pval) //出栈并获取栈顶元素bool GetTop(PLinkStack ps, ElemType* pval) //获取栈顶元素出栈并获取栈顶元素传入一个数据类型的指针ElemType * pval用来接收栈顶元素之后释放节点空间即可不要忘记将链栈的容量进行减一。获取栈顶元素直接用元素指针接收值即可//1.出栈并获取栈顶元素 bool Pop(PLinkStack ps, ElemType* pval) { assert(ps ! NULL); if (IsEmpty(ps))return false; //判空若为空无需出栈 PstackNode p ps-top-next; //先用p保存要出栈的节点的地址 ps-top-next p-next; //头节点连接后续节点 *pval p-data; //解应用指针用来接收栈顶元素 free(p); p NULL; ps-cursize--; //容量减一 return true; } //2.获取栈顶元素 bool GetTop(PLinkStack ps, ElemType* pval) { assert(ps ! NULL); if (IsEmpty(ps))return false; //判空 *pval ps-top-next-data; //直接接收值即可 return true; }函数测试2.5清空、销毁void ClearStack(PLinkStack ps) //清空void DestroyStack(PLinkStack ps) //销毁清空循环释放所有的有效节点即可销毁释放所有节点包括头节点//1.清空 void ClearStack(PLinkStack ps) { assert(ps ! NULL); if (IsEmpty(ps))return; PstackNode p ps-top-next; //p从第一个有效节点开始(头删) while (p ! NULL) { //p!NULL 则一直删除 ps-top-next p-next; //先连接后续节点 free(p); p ps-top-next; //重置p为第一个有效节点 } ps-cursize 0; //容量置0 } //2.销毁 void DestroyStack(PLinkStack ps) { assert(ps ! NULL); ClearStack(ps); //调用清空函数释放所有的有效节点 free(ps-top); //释放头节点 ps-top NULL; ps-cursize 0; //容量置空0 }三、结语链栈之韵代码留痕当最后一个节点在内存中安然归位当出栈的指针划过逻辑的轨迹我们与链栈的对话暂告段落。从结构体指针的精巧设计到入栈出栈的代码实现从 malloc 的节点诞生到 free 的资源轮回——每个细节都藏着编程的韵律秩序与自由的平衡抽象与具象的交融。链栈如诗以指针为笔、内存为纸书写“后进先出”的优雅代码似舞用函数作步、逻辑为韵演绎数据结构的生命力。这些冰冷的语法实则是人类智慧对“存储与运算”最浪漫的诠释。愿这篇博客不仅是技术的书签更是一扇窗让你看见代码背后的诗意理解数据结构是思维的体操、逻辑的艺术。未来面对链栈或其他挑战时愿你带着敬畏与热爱在0与1的宇宙里继续书写属于自己的“指针之诗”
RELATED

相关推荐

C++栅栏同步:从内存序到高性能实现与调优

C++栅栏同步:从内存序到高性能实现与调优

1. 项目概述:为什么我们需要深入理解栅栏同步?在C多线程编程的世界里,我们常常需要协调多个线程的执行顺序,确保它们在某个关键点“碰头”,然后再一起继续前进。想象一下一个大型数据处理流水线,有线程A负责…

📅 2026/9/11 20:57:45
Trae工具深度解析:专为Coze扣子智能体API流式集成设计的调试与交付方案

Trae工具深度解析:专为Coze扣子智能体API流式集成设计的调试与交付方案

1. 项目概述:Trae 工具在扣子智能体API集成中的真实价值定位“使用 Trae 工具轻松搞定扣子智能体API集成”——这个标题乍看像一句营销话术,但拆开来看,它精准击中了当前AI工程化落地中最普遍、最痛的三个断层:开发工具链割裂、AP…

📅 2026/9/9 15:41:57
5步解锁现代化魔兽地图编辑:HiveWE完全指南

5步解锁现代化魔兽地图编辑:HiveWE完全指南

5步解锁现代化魔兽地图编辑:HiveWE完全指南 【免费下载链接】HiveWE A Warcraft III world editor. 项目地址: https://gitcode.com/gh_mirrors/hi/HiveWE 还在为传统魔兽争霸III地图编辑器缓慢的加载速度和复杂的操作界面而烦恼吗?你是否曾经在等…

📅 2026/8/24 2:23:00
MORE NEWS

更多资讯

📰

Refine v5 与 Ant Design 认证实战:从自定义 AuthProvider 到 AuthPage 构建完整的用户认证体系

Refine v5 与 Ant Design 认证实战:从自定义 AuthProvider 到 AuthPage 构建完整的用户认证体系 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https…

📰

腰果缺陷检测YOLO数据集详解:目录、标签与训练实战

简介:面向目标检测与工业缺陷识别场景的腰果缺陷YOLO数据集,共5类:Broken、Defect、SplitDown、SplitUp、Whole,已按YOLOv5目录结构划分训练集3186张、验证集304张、测试集150张,每张图片均含对应txt标签,采…

📰

用Python可视化分析智能手机价格数据集:RAM如何左右定价?

简介:面向数据分析初学者、消费电子市场研究者及智能手机行业从业者的智能手机价格可视化分析资料包,聚焦品牌、型号、屏幕尺寸、处理器速度、内存大小、存储容量、摄像头规格、发布日期、价格等核心字段,通过真实数据集揭示价格与配置、品牌…

📰

基于深度学习1DCNN的轴承故障诊断:从振动信号到端到端分类实践

简介:基于深度学习的1DCNN轴承故障诊断源码包,面向机械故障诊断、工业预测性维护领域的工程师与研究人员,提供从振动信号预处理、1DCNN模型构建、训练优化到故障分类的完整实现方案。资源共50个文件,包体仅3.64MB,以Py…

📰

【信息科学与工程学】【数据中心】第四十五篇 Volcano + HAMi + K8s + GPU 的运营调度01

Volcano + HAMi + K8s + GPU 的运营调度算法补充。视为“GPU共享训练/推理运营”专项,编号用 GPU‑01 起。 编号 类别 模型配方 多/双/单Region+多/双/单AZ+边缘DC/边缘计算节点 IaaS/PaaS+SaaS服务层 产品及产品功能(可以多产品组合、多功能组合)及需要的软件/硬件资源…

📰

GPT Researcher 常见问题深度解析:从快速上手到成本控制与事实准确性保障

GPT Researcher 常见问题深度解析:从快速上手到成本控制与事实准确性保障 【免费下载链接】gpt-researcher An autonomous agent that conducts deep research on any data using any LLM providers 项目地址: https://gitcode.com/GitHub_Trending/gp/gpt-resear…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬