当前位置: 首页 > news >正文

栈的基本概念介绍

一、栈的核心定义与特性

是一种操作受限的线性数据结构。它只允许在一端进行数据的插入(入栈,Push)和删除(出栈,Pop)操作。这一端被称为栈顶,另一端则称为栈底

它遵循 LIFO 原则,即 后进先出。这是栈最核心、最基本的特性。

  • 后进:最后一个被添加进栈的元素。
  • 先出:这个最后进入的元素,将成为第一个被移除的元素。

生活比喻:

  • 一摞盘子:你只能从最顶部拿走(Pop)一个盘子,也只能将新的盘子放在(Push)这摞盘子的最顶部。
  • 弹夹:子弹被一颗颗压入(Push)弹夹,射击时最后压入的那颗子弹最先被打出(Pop)。

二、栈的基本操作

栈的核心操作通常有以下几种:

  1. Push (入栈):向栈顶添加一个新元素。
    • 操作:检查栈是否已满(对于固定大小的栈),然后将栈顶指针向上移动一位,在新位置存入数据。
  2. Pop (出栈):移除并返回栈顶元素。
    • 操作:检查栈是否为空,然后返回当前栈顶指针所指的元素,再将指针向下移动一位。
  3. Peek / Top (查看栈顶):返回栈顶元素但不移除它。
    • 操作:仅读取栈顶指针所指的元素,不移动指针。
  4. isEmpty (判空):检查栈是否为空。
  5. isFull (判满):检查栈是否已满(主要针对基于数组的实现)。

三、栈的实现方式

栈是一种逻辑结构,可以用两种主要的物理结构来实现:

特性基于数组的实现基于链表的实现
结构使用连续的内存块使用通过指针连接的节点
大小固定大小,可能发生栈溢出动态大小,理论上只要内存足够就可以扩展
性能所有操作的时间复杂度都是 O(1),因为直接通过索引访问所有操作的时间复杂度也是 O(1),因为只操作链表头部
优点实现简单,访问速度快,没有额外指针开销灵活,无需预先指定大小,不会出现“栈满”(除非内存耗尽)
缺点有最大容量限制,可能浪费空间每个元素需要额外空间存储指针

选择依据:如果需要确定性和高性能,且能预估最大大小,用数组。如果需要灵活性,不确定数据量大小,用链表。


四、栈的深远应用

栈不仅仅是教科书上的一个数据结构,更是计算机科学无处不在的基石。

  1. 函数调用(调用栈)

    • 这是栈最核心、最重要的应用。 当一个程序调用一个函数时,操作系统/运行时环境会创建一个栈帧并将其压入调用栈
    • 栈帧中存储了:
      • 函数的返回地址(执行完后回到哪里)
      • 函数的参数
      • 函数的局部变量
      • 上一栈帧的指针等上下文信息
    • 过程:主函数 main() 调用 funcA()funcA 的栈帧被压入栈顶。funcA() 又调用 funcB()funcB 的栈帧再被压入。当 funcB() 执行完毕,它的栈帧出栈,CPU回到 funcA() 的栈帧继续执行。这完美契合了LIFO原则。
    • 递归:递归函数本质上就是通过调用栈来实现的。每一次递归调用都会压入一个新的栈帧。如果递归深度太大,会导致栈溢出错误。
  2. 表达式求值(语法分析)

    • 编译器使用栈来计算表达式(如 3 + 4 * (5 - 2))或进行语法检查(如括号匹配)。
    • 后缀表达式(逆波兰表示法)求值:遇到操作数就入栈;遇到运算符就从栈顶弹出两个操作数进行计算,将结果再压回栈中。最后栈里剩下的就是最终结果。
    • 中缀转后缀:也需要用到栈来处理运算符的优先级。
    • 括号匹配:遍历字符串,遇到左括号 ({[ 就入栈;遇到右括号,就弹出栈顶元素看是否匹配。最后栈为空则匹配成功。
  3. 撤销机制

    • 几乎所有编辑软件(如文本编辑器、Photoshop)的“撤销”功能都是用栈实现的。
    • 你的每一个操作(键入文字、绘制笔画)都被作为一个状态或命令对象压入栈中。
    • 当你执行“撤销”时,就是将栈顶的命令弹出并执行其反向操作。“重做”功能通常会用另一个栈来存储被撤销的操作。
  4. 浏览器的前进与后退

    • 使用两个栈
      • 后退栈:当你访问新页面时,URL被压入后退栈。
      • 前进栈:当你点击“后退”按钮时,从后退栈弹出当前页面,并将其压入前进栈;点击“前进”时则相反。
  5. 内存管理(栈内存)

    • 在程序的内存布局中,专门有一块区域叫做调用栈,用于存储函数调用时的局部变量和上下文信息。这与第1点紧密相关。
    • 栈内存 的特性是自动分配和释放(通过移动栈指针),效率极高。与之相对的是堆内存,需要手动管理(如C中的malloc/free,C++中的new/delete)。

五、深入:硬件与系统层面的栈

栈的概念也深深植根于计算机硬件和操作系统设计中。

  • 线程栈:操作系统为每个线程分配一个独立的栈空间。这确保了线程在执行函数调用时互不干扰。
  • 中断处理:当硬件发生中断时,CPU会自动将当前程序的上下文(如寄存器状态)压入内核栈,处理完中断后再弹出恢复,从而保证被中断的程序能继续正常运行。
  • 栈指针寄存器:CPU中有一个专门的寄存器(如x86架构的ESP,ARM架构的SP)来永远指向当前栈顶的位置。任何入栈和出栈操作都通过移动这个寄存器来完成。

总结

层面栈的角色关键点
数据结构一种抽象的线性表LIFO原则,Push/Pop操作,数组/链表实现
算法应用解决问题的工具函数调用、表达式求值、括号匹配、回溯算法
系统内存内存布局的一部分存储局部变量、函数调用上下文,自动管理
硬件底层CPU直接支持的功能栈指针寄存器,中断处理,程序执行的基础

总而言之,栈是计算机科学中一个极其基础且强大的概念,它从最底层的硬件设计到顶层的应用开发无处不在,是理解程序如何运行的关键之一。

补充

栈底和栈顶:其中栈底的地址始终不变,为栈最高地址位。栈顶是指针SP指向的位置。栈顶的地址。

Variable n栈顶
FFFE_FFF8Variable1
FFFF_0000Variable0栈底
http://www.dtcms.com/a/360536.html

相关文章:

  • kafka、RabbitMQ结构
  • Qt QNetworkAccessManager 简述及例程
  • 畅问AI-AI机器人对话平台
  • dayjs ​JavaScript 时间日期处理库
  • 力扣hot100:轮转数组(常规思路与三步反转讲解)(189)
  • C#基础(②音乐播发器MCI(Media Control Interface))
  • CMake⼯程指南-3
  • 手写MyBatis第45弹:动态代理在MyBatis插件内核是如何织入扩展逻辑的
  • Linux软件升级方法总结
  • CF每日3题(1500-1600)
  • 在windows系统下安装Docker Desktop后迁移镜像位置
  • 科普:requirements.txt 和 environment.yml
  • 【系统分析师】高分论文:论面向服务方法在信息系统开发中的应用
  • 一些八股总结
  • Langflow Agents 技术深度分析
  • OpenCL C 平台与设备
  • (附源码)基于Vue的教师档案管理系统的设计与实现
  • 【开题答辩全过程】以 基于Java的网络购物平台设计与实现为例,包含答辩的问题和答案
  • LeetCode 3665. 统计镜子反射路径数目
  • react-virtualized React 应用中高效渲染大型列表和表格数据的库
  • Synchronized 概述
  • 【LeetCode】18、四数之和
  • LeeCode 37. 解数独
  • 并发编程——10 CyclicBarrier的源码分析
  • Selenium 等待机制:编写稳定可靠的自动化脚本
  • spi总线
  • 7.2elementplus的表单布局与模式
  • MCP SDK 学习二
  • 艾体宝案例 | 数据驱动破局:DOMO 如何重塑宠物零售门店的生存法则
  • Python 2025:AI代理、Rust与异步编程的新时代