【数据结构】堆、栈的区别

2023-11-19

heap 是堆,stack 是栈。

在编程语言中,内存分配方式主要包括,栈、堆、静态存储分配

  • 栈的内存是由操作系统自动分配/释放的,存放函数的参数值、局部变量等
  • 堆的内存是由程序员手动申请和释放的,对应C语言中的malloc函数和C++中的new、free。优点是设置的变量是由程序员自行决定的,使用相对灵活。但是分配内存后需要及时释放,否则会导致内存泄漏。但是现在的编程语言,如python可以自主回收不再使用的内存。
  • 静态存储分配就是所谓的全局变量,整个程序的运行期间都存在,直到程序运行结束时才释放。

而数据结构中的堆和栈则是两种数据结构

栈是特殊的线性表,元素的插入、删除,遵循“先进后出”原则。可以用顺序表也可以用链表实现。一般用顺序表实现的多用于查询,如果插入删除比较频繁则多使用链表

堆是一种经过排序的树形数据结构,常用于实现优先级队列,分大顶堆和小顶堆。类似于一种特殊的完全二叉树,可以看成是完全二叉树的数组对象。每个结点都大于或小于它的孩子结点

 

内存分配中的栈与堆主要存在如下区别。

1) 分配与释放方式

栈内存是由编译器自动分配与释放的,它有两种分配方式:静态分配和动态分配。

  • 静态分配是由编译器自动完成的,如局部变量的分配(即在一个函数中声明一个 int 类型的变量i时,编译器就会自动开辟一块内存以存放变量 i)。与此同时,其生存周期也只在函数的运行过程中,在运行后就释放,并不可以再次访问。
  • 动态分配由 alloca 函数进行分配,但是栈的动态分配与堆是不同的,它的动态分配是由编译器进行释放,无需任何手工实现。值得注意的是,虽然用 alloca 函数可以实现栈内存的动态分配,但 alloca 函数的可移植性很差,而且在没有传统堆栈的机器上很难实现。因此,不宜使用于广泛移植的程序中。当然,完全可以使用 C99 中的变长数组来替代 alloca 函数。

而堆内存则不相同,它完全是由程序员手动申请与释放的,程序在运行的时候由程序员使用内存分配函数(如 malloc 函数)来申请任意多少的内存,使用完再由程序员自己负责使用内存释放函数(如 free 函数)释放内存

对栈内存的自动释放而言,虽然堆上的数据只要程序员不释放空间就可以一直访问,但是,如果一旦忘记了释放堆内存,那么将会造成内存泄漏,导致程序出现致命的潜在错误。

2) 分配的碎片问题

对堆来说,频繁分配和释放(malloc / free)不同大小的堆空间势必会造成内存空间的不连续,从而造成大量碎片,导致程序效率降低;而对栈来讲,则不会存在这个问题。

3) 分配的效率

栈是机器系统提供的数据结构,计算机会在底层对栈提供支持,例如,分配专门的寄存器存放栈的地址,压栈出栈都有专门的执行指令,所以栈的效率比较高。一般而言,只要栈的剩余空间大于所申请空间,系统就将为程序提供内存,否则将报异常提示栈溢出。

而堆则不同,它是由编程语言函数库提供的,它的机制相当复杂。例如,为了分配一块堆内存,首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序。而对于大多数系统,会在这块内存空间的首地址处记录本次分配的大小,这样,代码中的 delete 语句才能正确释放本内存空间。另外,由于找到的堆节点的大小不一定正好等于申请的大小,系统会自动将多余的那部分重新放入空闲链表中。很显然,堆的分配效率比栈要低得多。

4) 申请的大小限制

由于操作系统是用链表来存储空闲内存地址(内存区域不连续)的,同时链表的遍历方向是由低地址向高地址进行的。因此,堆内存的申请大小受限于计算机系统中有效的虚拟内存。

而栈则不同,它是一块连续的内存区域,其地址的增长方向是向下进行的,向内存地址减小的方向增长。由此可见,栈顶的地址和栈的最大容量一般都是由系统预先规定好的,如果申请的空间超过栈的剩余空间时,将会提示溢出错误。由此可见,相对于堆,能够从栈中获得的空间相对较小。

5) 存储的内容

对栈而言,一般用于存放函数的参数与局部变量等。例如,在函数调用时,第一个进栈的是(主函数中的)调用处的下一条指令(即函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数 C 编译器中,参数是由右往左入栈的,最后是函数中的局部变量(注意 static 变量是不入栈的)。

当本次函数调用结束后,遵循“先进后出”(或者称为“后进先出”)的规则,局部变量先出栈,然后是参数,最后栈顶指针指向最开始保存的地址,也就是主函数中的下一条指令,程序由该点继续运行。

对堆而言,具体存储内容由程序员根据需要决定存储数据。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【数据结构】堆、栈的区别 的相关文章

  • C语言,求取数组的序亏:已知一个整数数组,求出个数组中每个元素在整个 数组的排序。

    要求获取整数数组中每个元素的排序 可以使用以下方法 1 定义一个结构体数组 其中每个结构体包含数组元素的值和索引 2 遍历整数数组 将每个元素与其索引一起存储到结构体数组中 3 对结构体数组进行排序 按照元素的值进行升序排序 4 遍历排序后
  • 八大排序(插入排序 | 选择排序 | 冒泡排序)

    在我们内存中我们一般会有一些没有顺序的数据 我们成为内排序 而今天分享八大排序的是时间复杂度为O N 2 的插入排序 选择排序和教学意义比较强的冒泡排序 插入排序 这是插入排序的动图 通过动图我们也是可以看到我们的插入排序的思想 从当前的位
  • C语言之变量的存储方式和生存周期

    一 变量的存储方式 C语言变量的存储有两种方式 静态存储方式和动态存储方式 相应的生产期也有两种 静态生存期和自动生存期 静态存储方式 在程序运行前为变量内存分配内存 在程序结束后回收变量的内存 静态生存期 动态存储方式 在程序运行过程中
  • 代码随想录算法训练营Day3 | 203.移除链表元素、707.设计链表、59.螺旋矩阵II

    LeetCode 203 移除链表元素 本题思路 就是常规的移除链表中的元素的操作 需要注意的点 头节点 head val val 的情况的处理 如果 head val val 就要继续往后 head head next 因此我们要遍历到第
  • 剑指 Offer(第2版)面试题 35:复杂链表的复制

    剑指 Offer 第2版 面试题 35 复杂链表的复制 剑指 Offer 第2版 面试题 35 复杂链表的复制 解法1 模拟 剑指 Offer 第2版 面试题 35 复杂链表的复制 题目来源 48 复杂链表的复刻 解法1 模拟 算法 复制原
  • LeetCode326. Power of Three

    文章目录 一 题目 二 题解 一 题目 Given an integer n return true if it is a power of three Otherwise return false An integer n is a po
  • 数据结构 数组与字符串

    介绍 数组的基础 定义和声明 基本定义 在C语言中 数组可以被定义为一系列相同类型的元素的集合 每个元素在内存中连续排列 可以通过索引 通常是从0开始的整数 来访问 数组的声明 数组在C语言中的声明包括元素类型 数组名和大小 例如 声明一个
  • 深度学习目标检测全连接层什么意思

    在深度学习目标检测中 通常我们使用卷积神经网络 Convolutional Neural Network CNN 进行特征提取 CNN 的主要结构包括卷积层和池化层 用于从输入图像中提取特征 然而 为了最终输出目标的类别和位置信息 通常在网
  • 力扣每日一题:162. 寻找峰值(2023-12-18)

    力扣每日一题 题目 162 寻找峰值 日期 2023 12 18 用时 10 m 9 s 时间 0 ms 内存 40 54 MB 代码 class Solution public int findPeakElement int nums i
  • 华为OD机试 Java 【最大载货量】

    描述 在火车站旁的货运站 小明负责调度2K辆中转车 其中K辆用于干货 K辆用于湿货 每批到站的货物来自不同的供货商 需要按照顺序装入中转车 注意 一个供货商的货物只能装在一辆车上 不能分开 但是 一辆车可以放多个供货商的货物 问题是 要让所
  • 华为OD机试 C++【最大载货量】

    描述 在火车站旁的货运站 小明负责调度2K辆中转车 其中K辆用于干货 K辆用于湿货 每批到站的货物来自不同的供货商 需要按照顺序装入中转车 注意 一个供货商的货物只能装在一辆车上 不能分开 但是 一辆车可以放多个供货商的货物 问题是 要让所
  • 【数据结构和算法】 K 和数对的最大数目

    其他系列文章导航 Java基础合集 数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一 题目描述 二 题解 2 1 方法一 双指针排序 三 代码 3 1 方法一 双指针排序 3
  • 数组对象排序 (arr.sort())

    前端面试题库 面试必备 推荐 地址 前端面试题库 对象排序 arr sort 描述 方法sort 将在原数组上对 数组元素 进行排序 即排序时不创建新的数组副本 如果想按照别的顺序进行排序 就必须提供比较函数 该函数要比较两个值 然后返回一
  • 代码随想录算法训练营第42天| ● 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集

    416 分割等和子集 已解答 中等 相关标签 相关企业 给你一个 只包含正整数 的 非空 数组 nums 请你判断是否可以将这个数组分割成两个子集 使得两个子集的元素和相等 示例 1 输入 nums 1 5 11 5 输出 true 解释
  • 冒泡排序/选择排序/插入排序/快速排序/归并排序/桶排序/堆排序/希尔排序/计数排序/基数排序/二分查找/广度优先搜索/深度优先搜索

    排序算法 冒泡排序 Bubble Sort 通过重复地比较相邻的元素并交换它们 使得最大 或最小 的元素逐渐移动到列表的一端 从而实现排序 选择排序 Selection Sort 在未排序的部分中 选择最小 或最大 的元素 并将其放置在已排
  • 计算机基础:网络基础

    一 网线制作 1 制作所需要工具 网线 网线制作标准 2 水晶头使用 3 网线钳使用 4 视频教学 网线制作 二 集线器 交换机介绍 1 OSI七层模型 Open System Interconnect 即开放系统互连参考模型 是由 ISO
  • LeetCode 2397. 被列覆盖的最多行数,状态压缩优化回溯法

    一 题目 1 题目描述 给你一个下标从 0 开始 大小为 m x n 的二进制矩阵 matrix 另给你一个整数 numSelect 表示你必须从 matrix 中选择的 不同 列的数量 如果一行中所有的 1 都被你选中的列所覆盖 则认为这
  • 【每日一题】2397. 被列覆盖的最多行数-2024.1.4

    题目 2397 被列覆盖的最多行数 给你一个下标从 0 开始 大小为 m x n 的二进制矩阵 matrix 另给你一个整数 numSelect 表示你必须从 matrix 中选择的 不同 列的数量 如果一行中所有的 1 都被你选中的列所覆
  • 排序:计数排序

    一 概念 计数排序是非比较排序 是对哈希直接定址法的变形应用 二 思想 利用数组统计相同数据出现的次数 例如整型数据m出现n次 就在数组m位置记录数据为n 最后从头遍历数组打印数据即可 通俗来讲就是 数组下标即为数据 下标所指位置的值即为数
  • 用栈实现队列(OJ中报错的处理)

    用栈实现队列 ERROR AddressSanitizer myQueueFree函数中栈的释放处现了问题 没有调用StackDestory而是直接free了 这个是栈初始化时 capacity与malloc申请的空间大小没有匹配 请你仅使

随机推荐

  • 【头歌-Python】Python第六章作业(初级)

    第1关 列表的属性与方法 任务描述 初始化一个空列表 输入一个正整数 n 接下来 你将被要求输入 n 个指令 每得到一个指令后 根据指令的字符串进行对应的功能操作 指令形式及对应功能如下 insert i e 在第 i 个位置插入整数 e
  • 5秒之后自动跳转页面

  • 基础备忘:数组指针与对一维数组名取地址

    一 指向一维数组的数组指针 数组指针是指向一个数组的指针 如 int p 10 p是一个指针 指向一个包含10个元素的一维数组 数组元素是整形 如果写成了int p 10 则是一个指针数组 由于 的优先级比 的高 p先与 结合 p就是数组类
  • Mac maven删除与安装

    Mac maven删除与安装 一 删除maven 找到maven安装目录 打开终端输入 mvn version找到安装目录 终端输入sudo rm rf maven的路径 二 安装maven 到maven官网下载 选择apache mave
  • [2021首届“陇剑杯”网络安全大赛] SQL注入

    2021首届 陇剑杯 网络安全大赛 SQL注入 题目描述 某应用程序被攻击 请分析日志后作答 黑客在注入过程中采用的注入手法叫 布尔盲注 格式为4个汉字 例如 拼搏努力 黑客在注入过程中 最终获取flag的数据库名 表名和字段名是 Sqli
  • vue3中实现el-dialog弹窗

    vue3中的父子组件传递依然和vue2中的一样使用props和emit 但是写法略有不同 emit 自定义事件 子传父 props 父传子 父组件中
  • 【数学建模】预测模型——多元回归分析 SPSS实现

    线性回归介绍 回归分析是研究变量之间因果关系的一种统计模型 因变量就是结果 自变量就是原因 基于结果变量 因变量 的种类 回归分析可分为 线性回归 因变量为连续变量 logistic回归 因变量为分类变量 柏松回归 因变量为计数变量 这三种
  • config:fail,Error: 系统错误,错误码:40048,invalid url domain

    调用微信接口报出的错误 这个错误原因是因为安全域名配置错误 分两种情况 若是公众号的测试号 你完全可以写一个内网ip 比如192 168 1 100 8080 不必内网穿透 当然如果是需要微信回调的话还要外网可访问 若是公众号的正式号 可以
  • 使用Flink1.16.0的SQLGateway迁移Hive SQL任务

    使用Flink的SQL Gateway迁移Hive SQL任务 前言 我们有数万个离线任务 主要还是默认的DataPhin调度CDP集群的Hive On Tez这种低成本任务 当然也有PySpark 打Jar包的Spark和打Jar包的Fl
  • shell 脚本编写总结(1)

    知识点1 变量 1 环境变量 1 变量 BASH Bash Shell的全路径 比如 echo BASH 2 变量 BASH VERSION Bash Shell的版本号 3 变量 EUID 记录当前用户的UID root用户值为0 4 F
  • vue + 高德地图 + 标记点

    其他 高德地图引入及使用 vue 高德地图 标记点 变大变小闪烁动画 多标记点 同一位置标记点显示个数 增加标记点 绘制地图 this map new AMap Map map resizeEnable true center 120 35
  • 区块链学习笔记(一)——比特币概念以及密码学相关的知识

    自己做一些让自己读得懂的笔记 区块链学习笔记 一 1 Bitcoin History 1 1 一个关于bitcoin的时间线 2 Crytography of the Blockchain 2 1 the Hash function 2 1
  • 时间序列预测之ARMA、ARIMA序列及季节性序列matlab实现

    ARMA是一种平稳时间序列模型 即均值和协方差不随时间的平移而改变 ARMA有三种类型 AR序列 MA序列 ARMA序列 但是由于ARMA只能处理平稳序列 而现实中的问题往往有趋势性或周期性等 为了得到平稳序列 我们对数据进行差分运算 使得
  • 【编辑器】UnityConsole界面双击日志跳转

    环境 发布正式包时 Unity的原生Log肯定是要屏蔽的 最常用的做法就是自己封装一下 实现一个debug 不过这样的话 双击跳转就会去到Debug类里面去 为了方便查bug 实现一下日志跳转 实现 看了一下网上的资料 思路应该就是通过类型
  • 【系统移植】开发板的启动过程(认识uboot)

    在系统移植之前 需要先了解开发板启动的大致流程 了解了大致流程后 才知道开发板启动需要哪些东西 了解开发板启动的时候 一定会遇到闻所未闻的东西 所以我们了解的顺序是 了解开发板启动时涉及到的部件 了解启动过程中涉及到的文件 uboot 内核
  • msfvenom生成各种Payload命令

    msfvenom生成各种Payload命令 msfvenom l 列出所有模块 攻击载荷 Binaries linux msfvenom p linux x86 meterpreter reverse tcp LHOST
  • Ubuntu 安装配置NFS网络文件系统服务器(详细)

    现在我的电脑连接情况 Ubuntu 安装配置NFS服务器 一 安装NFS服务器1 1 安装Ubuntu nfs服务器端 sudo apt get install nfs kernel server 很显然 我已经安装过了 继续往下走 1 2
  • 从零开始刷题1

    又一道简单等级的题 小白打小怪 最大时间 给定一个由 4 位数字组成的数组 返回可以设置的符合 24 小时制的最大时间 最小的 24 小时制时间是 00 00 而最大的是 23 59 从 00 00 午夜 开始算起 过得越久 时间越大 以长
  • 网络编程是什么

    转载 http peixun eol cn company company article detail php articleid 15033 对于初学者 或者没有接触过网络编程的程序员 会觉得网络编程涉及的知识很高深 很难 其实这是一种
  • 【数据结构】堆、栈的区别

    heap 是堆 stack 是栈 在编程语言中 内存分配方式主要包括 栈 堆 静态存储分配 栈的内存是由操作系统自动分配 释放的 存放函数的参数值 局部变量等 堆的内存是由程序员手动申请和释放的 对应C语言中的malloc函数和C 中的ne