栈与队列之栈入门攻略:从核心概念到数组实现

🏠个人主页:黎雁
🎬作者简介:C/C++/JAVA后端开发学习者
❄️个人专栏:C语言、数据结构(C语言)、EasyX、游戏、规划、程序人生
✨ 从来绝巘须孤往,万里同尘即玉京

文章目录

  • 栈与队列之栈入门攻略:从核心概念到数组实现✨
    • 文章摘要
    • 一、知识回顾:线性表的核心本质
    • 二、栈的核心概念:什么是“后进先出”?📚
      • 1. 栈的定义
      • 2. 栈的关键操作术语
      • 3. 栈的实现方式对比:数组 vs 链表
    • 三、栈的工程化实现:数组版栈完整代码💻
      • 1. 头文件定义(stack.h):接口声明
      • 2. 源文件实现(stack.c):核心逻辑
        • (1)栈的初始化
        • (2)栈的销毁
        • (3)入栈操作(压栈)
        • (4)出栈操作(弹栈)
        • (5)获取栈顶元素
        • (6)获取栈大小 & 判断栈为空
    • 四、核心设计思想:低耦合、高内聚🎯
      • 思考:为什么要把StackSize、StackEmpty封装成函数?
    • 五、写在最后

栈与队列之栈入门攻略:从核心概念到数组实现✨

你好!欢迎来到线性表系列的全新篇章——栈与队列篇的第一讲。

在前面的内容中,我们已经吃透了顺序表和链表这两大基础线性表,从底层实现到实战刷题,完成了从理论到实践的跨越。而今天要学习的,作为一种特殊的线性表,是数据结构世界里不可或缺的核心角色,它的“后进先出”特性在算法解题、工程开发中都有着广泛应用,比如括号匹配、函数调用栈、表达式求值等场景都离不开它。

准备好了吗?让我们一起解锁栈的核心知识,从概念到实现,彻底掌握这个“个性十足”的线性表!🚀


文章摘要

本文聚焦线性表中的栈结构,系统讲解栈的核心概念、“后进先出”特性及数组/链表两种实现方式的优劣对比,最终选择数组作为最优实现方案。通过完整的工程化代码(头文件+源文件),详细拆解栈的初始化、销毁、入栈、出栈等核心操作,补充top指针两种初始化方式的关键细节,结合软件工程“低耦合、高内聚”思想解析代码设计,夯实栈的底层实现基础。

阅读时长:约20分钟
阅读建议

  1. 基础薄弱者:先吃透栈的核心特性,再对照代码理解实现逻辑
  2. 工程开发者:重点关注数组扩容、内存释放等细节,借鉴代码封装思想
  3. 面试备考者:牢记栈的特性、实现方式及典型应用场景
  4. 查漏补缺者:直接查看代码实现中的关键注释和易错点

一、知识回顾:线性表的核心本质

在学习栈之前,我们先回顾下线性表的核心特征:

  • 线性表是数据元素呈线性排列的结构,每个元素有唯一的前驱和后继(除首尾)
  • 顺序表:物理存储连续,随机访问快,但插入删除效率低
  • 链表:物理存储不连续,插入删除效率高,但随机访问慢

而栈,正是基于线性表实现的受限数据结构——它只允许在一端进行操作,这也让它拥有了独一无二的特性!


二、栈的核心概念:什么是“后进先出”?📚

1. 栈的定义

栈是一种特殊的线性表,只允许在固定的一端进行插入和删除操作,遵循后进先出(LIFO = Last In First Out)原则。

举个生活中的例子:

  • 往弹夹里装子弹:后装进去的子弹,先被打出来 → 这就是栈的“后进先出”
  • 叠盘子:最后叠上去的盘子,最先被拿走 → 完美契合栈的特性

2. 栈的关键操作术语

操作名称说明操作位置
压栈/入栈/进栈向栈中添加元素栈顶(唯一操作端)
出栈/弹栈从栈中删除元素栈顶(唯一操作端)
栈顶允许操作的这一端(栈的“顶端”)-
栈底固定不动的另一端(栈的“底部”)-

3. 栈的实现方式对比:数组 vs 链表

栈有两种主流实现方式,我们来详细对比优劣,选择最优方案:

实现方式核心思路优点缺点
数组(推荐)用数组尾端作为栈顶,入栈=尾插、出栈=尾删① 操作效率O(1) ② 随机访问快 ③ 实现简单空间不足时需要扩容(可通过预分配缓解)
链表① 单链表:头节点作为栈顶(头插头删)
② 双向链表:尾节点作为栈顶
无需扩容,按需分配内存① 单链表需额外处理指针 ② 双向链表实现复杂 ③ 缓存命中率低

结论:数组实现栈是最优选择!

  • 数组尾插尾删的时间复杂度都是O(1),完全匹配栈的操作需求
  • 虽然存在扩容成本,但扩容频率低(通常按2倍扩容),整体效率远高于链表
  • 符合《深入理解计算机系统》中“局部性原理”,缓存命中率更高

三、栈的工程化实现:数组版栈完整代码💻

我们采用“头文件+源文件”的工程化结构实现栈,保证代码的规范性和可维护性。

1. 头文件定义(stack.h):接口声明

头文件负责定义栈的结构体和函数接口,是栈的“对外接口规范”:

#pragmaonce#include<stdio.h>#include<stdbool.h>#include<assert.h>#include<stdlib.h>// 定义栈存储的数据类型(方便后续修改)typedefintSTDataType;// 栈的结构体定义(数组实现)typedefstructStack{STDataType*a;// 存储数据的数组指针inttop;// 栈顶指针(关键!)intcapacity;// 数组的容量}ST;// 栈的核心操作接口voidStackInit(ST*ps);// 初始化栈voidStackDestroy(ST*ps);// 销毁栈(释放内存)voidStackPush(ST*ps,STDataType x);// 入栈(压栈)voidStackPop(ST*ps);// 出栈(弹栈)STDataTypeStackTop(ST*ps);// 获取栈顶元素intStackSize(ST*ps);// 获取栈中元素个数boolStackEmpty(ST*ps);// 判断栈是否为空

2. 源文件实现(stack.c):核心逻辑

源文件负责实现头文件声明的函数,是栈的“内部实现细节”:

(1)栈的初始化
#include"stack.h"voidStackInit(ST*ps)// 初始化栈{assert(ps);// 确保传入的栈指针不为NULL// 初始分配4个元素的空间(可根据需求调整)ps->a=(STDataType*)malloc(sizeof(STDataType)*4);if(ps->a==NULL)// 内存分配失败处理{perror("malloc fail");exit(1);// 终止程序}ps->capacity=4;// 初始容量为4ps->top=0;// 🌟 关键:top=0表示指向栈顶元素的下一个位置// 补充:若top=-1,表示指向栈顶元素本身(两种方式都可,需统一逻辑)}

💡关键细节:top指针的两种初始化方式

top初始值含义入栈逻辑出栈逻辑栈顶元素获取
0指向栈顶元素的下一个位置ps->a[ps->top] = x; ps->top++ps->top–ps->a[ps->top-1]
-1指向栈顶元素本身ps->top++; ps->a[ps->top] = xps->top–ps->a[ps->top]
(2)栈的销毁
voidStackDestroy(ST*ps)// 销毁栈(必须!避免内存泄漏){assert(ps);free(ps->a);// 释放数组内存ps->a=NULL;// 置空指针,防止野指针ps->top=0;// 重置栈顶ps->capacity=0;// 重置容量}
(3)入栈操作(压栈)
voidStackPush(ST*ps,STDataType x)// 入栈(尾插){assert(ps);// 扩容判断:栈满时扩容(2倍扩容)if(ps->top==ps->capacity){STDataType*tmp=(STDataType*)realloc(ps->a,ps->capacity*2*sizeof(STDataType));if(tmp==NULL){perror("realloc fail");exit(1);}ps->a=tmp;ps->capacity*=2;// 容量翻倍}// 入栈核心逻辑ps->a[ps->top]=x;ps->top++;}
(4)出栈操作(弹栈)
voidStackPop(ST*ps)// 出栈(尾删){assert(ps);assert(!StackEmpty(ps));// 栈空时禁止出栈ps->top--;// 只需移动top指针,无需真正删除数据(覆盖即可)}
(5)获取栈顶元素
STDataTypeStackTop(ST*ps)// 获取栈顶元素{assert(ps);assert(!StackEmpty(ps));// 栈空时禁止获取returnps->a[ps->top-1];// 对应top=0的初始化方式}
(6)获取栈大小 & 判断栈为空
intStackSize(ST*ps)// 获取栈中元素个数{assert(ps);returnps->top;// top的值就是元素个数(top=0的情况)}boolStackEmpty(ST*ps)// 判断栈是否为空{assert(ps);returnps->top==0;// top=0 → 空栈}

四、核心设计思想:低耦合、高内聚🎯

思考:为什么要把StackSize、StackEmpty封装成函数?

可能有同学会问:这两个函数逻辑简单,直接在测试代码里写ps->top == 0不就行了?

这就涉及到软件工程的核心思想——低耦合、高内聚

  1. 高内聚:栈的所有操作逻辑都集中在stack.c中,对外只暴露统一接口,便于维护和修改(比如后续把top初始值改成-1,只需修改栈内部代码,无需改测试代码)
  2. 低耦合:测试代码只需调用接口,无需关心栈的内部实现细节,降低代码之间的依赖
  3. 鲁棒性:函数内部有断言检查(如assert(ps)),能提前发现错误,而直接写表达式无法做到

简单来说:封装是为了让代码更健壮、更易维护


五、写在最后

恭喜你!在这一篇中,你已经掌握了栈的核心知识:

  • 理解了栈“后进先出”的核心特性
  • 对比了数组/链表两种实现方式,选择了最优方案
  • 完成了栈的工程化代码实现,掌握了top指针的关键细节
  • 理解了“低耦合、高内聚”的软件工程思想

栈作为基础数据结构,是后续学习的重要铺垫:

  • 算法层面:括号匹配、表达式求值、DFS(深度优先搜索)都离不开栈
  • 工程层面:函数调用栈、浏览器前进后退功能都基于栈实现

下一篇,我们将学习栈的“好搭档”——队列,它遵循“先进先出”原则,和栈形成完美互补。敬请期待!😜


点赞+收藏+关注,跟着系列内容一步步吃透数据结构!你的支持是我创作的最大动力~👍

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

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

相关文章

勒索软件谈判对话监控:Qwen3Guard-Gen-8B提供风险评级

勒索软件谈判对话监控&#xff1a;Qwen3Guard-Gen-8B提供风险评级 在金融客服系统中&#xff0c;一条看似普通的用户消息突然弹出&#xff1a;“你们的数据已经被加密&#xff0c;支付50万美元BTC到指定地址&#xff0c;否则我们将公开全部财务记录。”这不是演习——而是真实发…

AEUX:设计稿到动画的无缝转换终极指南

AEUX&#xff1a;设计稿到动画的无缝转换终极指南 【免费下载链接】AEUX Editable After Effects layers from Sketch artboards 项目地址: https://gitcode.com/gh_mirrors/ae/AEUX 你是否曾为设计稿到动效的转换过程感到头疼&#xff1f;图层属性丢失、格式不兼容、反…

BetterNCM:重新定义你的音乐世界

BetterNCM&#xff1a;重新定义你的音乐世界 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 你是否曾经觉得音乐播放器缺少了些什么&#xff1f;那些标准化的界面、固定的功能布局&…

Magisk Root工具完整指南:从入门到精通

Magisk Root工具完整指南&#xff1a;从入门到精通 【免费下载链接】Magisk The Magic Mask for Android 项目地址: https://gitcode.com/GitHub_Trending/ma/Magisk Android设备的Root权限获取一直是技术爱好者关注的热点。Magisk作为当前最流行的Root解决方案&#xf…

栈与队列之队列入门攻略:从核心概念到链表实现

&#x1f3e0;个人主页&#xff1a;黎雁 &#x1f3ac;作者简介&#xff1a;C/C/JAVA后端开发学习者 ❄️个人专栏&#xff1a;C语言、数据结构&#xff08;C语言&#xff09;、EasyX、游戏、规划、程序人生 ✨ 从来绝巘须孤往&#xff0c;万里同尘即玉京 文章目录栈与队列之队…

WarcraftHelper终极优化指南:让魔兽争霸3在现代系统完美运行

WarcraftHelper终极优化指南&#xff1a;让魔兽争霸3在现代系统完美运行 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款专为魔兽…

神经网络绘图革命:NN-SVG如何让复杂架构可视化变得轻而易举

神经网络绘图革命&#xff1a;NN-SVG如何让复杂架构可视化变得轻而易举 【免费下载链接】NN-SVG NN-SVG: 是一个工具&#xff0c;用于创建神经网络架构的图形表示&#xff0c;可以参数化地生成图形&#xff0c;并将其导出为SVG文件。 项目地址: https://gitcode.com/gh_mirro…

学术论文代写服务监测:Qwen3Guard-Gen-8B识别违规中介广告

学术论文代写服务监测&#xff1a;Qwen3Guard-Gen-8B识别违规中介广告 在教育内容平台日益繁荣的今天&#xff0c;AI生成技术正被广泛应用于智能问答、写作辅助和学习支持。然而&#xff0c;这股技术浪潮也催生了一些灰色地带——不法中介利用语义模糊的表达&#xff0c;在论坛…

OpenCore Legacy Patcher终极指南:为老旧Mac设备解锁新生命

OpenCore Legacy Patcher终极指南&#xff1a;为老旧Mac设备解锁新生命 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否拥有一台曾经风光无限的Mac设备&#xff0c;…

本地Cookie导出神器:Get-cookies.txt-LOCALLY完全使用指南

本地Cookie导出神器&#xff1a;Get-cookies.txt-LOCALLY完全使用指南 【免费下载链接】Get-cookies.txt-LOCALLY Get cookies.txt, NEVER send information outside. 项目地址: https://gitcode.com/gh_mirrors/ge/Get-cookies.txt-LOCALLY 还在为网站登录状态丢失而烦…

TegraRcmGUI:高效实现Switch设备自定义系统注入的完整指南

TegraRcmGUI&#xff1a;高效实现Switch设备自定义系统注入的完整指南 【免费下载链接】TegraRcmGUI C GUI for TegraRcmSmash (Fuse Gele exploit for Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/te/TegraRcmGUI TegraRcmGUI是一款基于C开发的图形化注…

AI-Shoujo HF Patch 增强补丁:全面解锁游戏创作潜能的专业指南

AI-Shoujo HF Patch 增强补丁&#xff1a;全面解锁游戏创作潜能的专业指南 【免费下载链接】AI-HF_Patch Automatically translate, uncensor and update AI-Shoujo! 项目地址: https://gitcode.com/gh_mirrors/ai/AI-HF_Patch AI-Shoujo HF Patch 是一款专为 AI-Shoujo…

康复训练指导生成需谨慎:Qwen3Guard-Gen-8B介入

康复训练指导生成需谨慎&#xff1a;Qwen3Guard-Gen-8B介入 在智能健康助手日益普及的今天&#xff0c;用户只需一句“我腰疼怎么恢复”&#xff0c;系统便能秒级生成一套看似专业的康复方案。这背后是大语言模型&#xff08;LLM&#xff09;的强大生成能力&#xff0c;但同时也…

AirPodsDesktop完整指南:在Windows系统上实现苹果AirPods专业级功能体验

AirPodsDesktop完整指南&#xff1a;在Windows系统上实现苹果AirPods专业级功能体验 【免费下载链接】AirPodsDesktop ☄️ AirPods desktop user experience enhancement program, for Windows and Linux (WIP) 项目地址: https://gitcode.com/gh_mirrors/ai/AirPodsDesktop…

Django Widget Tweaks 终极指南:3分钟快速美化你的表单

Django Widget Tweaks 终极指南&#xff1a;3分钟快速美化你的表单 【免费下载链接】django-widget-tweaks Tweak the form field rendering in templates, not in python-level form definitions. CSS classes and HTML attributes can be altered. 项目地址: https://gitc…

Magisk模块开发实战:从零构建Android系统增强工具

Magisk模块开发实战&#xff1a;从零构建Android系统增强工具 【免费下载链接】Magisk The Magic Mask for Android 项目地址: https://gitcode.com/GitHub_Trending/ma/Magisk 模块化系统的技术优势 Magisk模块系统为Android设备提供了一种非侵入式的系统修改方案。相…

BetterNCM插件管理安装教程:10分钟掌握高效配置技巧

BetterNCM插件管理安装教程&#xff1a;10分钟掌握高效配置技巧 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 还在为网易云音乐插件安装的复杂流程而困扰吗&#xff1f;面对手动配置…

Applite 2024:macOS软件管理的终极智能解决方案权威评测

Applite 2024&#xff1a;macOS软件管理的终极智能解决方案权威评测 【免费下载链接】Applite User-friendly GUI macOS application for Homebrew Casks 项目地址: https://gitcode.com/gh_mirrors/ap/Applite 在macOS生态系统中&#xff0c;软件管理始终是技术团队面临…

STM32F103通过Keil5烧录程序的全面讲解

STM32F103烧录全攻略&#xff1a;从零开始用Keil5部署你的第一段代码你有没有过这样的经历&#xff1f;电路板焊好了&#xff0c;ST-Link插上了&#xff0c;Keil也打开了——结果一点击“下载”&#xff0c;弹窗却冷冰冰地告诉你&#xff1a;“No target connected”。那一刻&a…

Vue Admin Template:轻量级后台管理系统开发指南

Vue Admin Template&#xff1a;轻量级后台管理系统开发指南 【免费下载链接】vue-admin-template Vue 轻量级后台管理系统基础模板 项目地址: https://gitcode.com/gh_mirrors/vue/vue-admin-template 在当今快速发展的前端开发领域&#xff0c;拥有一个高质量的模板能…