1. 前言
堆(Heap)与栈(Stack)不同场景下,堆与栈代表不同的含义。一般情况下,有两层含义:
- 程序内存布局场景下,堆与栈表示两种内存管理方式;
- 数据结构场景下,栈是一种先进后出的数据结构,堆则是一种排序方式
2. 内存分配方式
以C语言的内存管理(代码段、数据段,栈,堆)为例
段名 | 内容 |
---|---|
代码段 | 用于存放程序的二进制代码的空间 |
数据段 | 常量、已初始化全局变量、已初始化全局静态变量、局部静态变量 |
栈 | 由编译器自动分配释放,存放函数的参数值,局部变量等值。注:其操作方式类似于数据结构中的栈 |
堆 | 由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。注:堆和数据结构中的堆不一样 |
2.1. 栈简介
栈由操作系统自动分配释放 ,用于存放函数的参数值、局部变量等,其操作方式类似于数据结构中的栈。
函数中定义的局部变量按照先后定义的顺序依次压入栈中,也就是说相邻变量的地址之间不会存在其它变量。栈的内存地址生长方向与堆相反,由高到底,所以后定义的变量地址低于先定义的变量。
栈中存储的数据的生命周期随着函数的执行完成而结束。
2.2. 堆简介
堆由开发人员分配和释放, 若开发人员不释放,程序结束时由 OS 回收,分配方式类似于链表。
堆的内存地址生长方向与栈相反,由低到高,但需要注意的是,后申请的内存空间并不一定在先申请的内存空间的后面,原因是先申请的内存空间一旦被释放,后申请的内存空间则会利用先前被释放的内存,从而导致先后分配的内存空间在地址上不存在先后关系。
堆中存储的数据若未释放,则其生命周期等同于程序的生命周期。
3. 数据结构中
3.1. 栈简介
栈是一种运算受限的线性表,其限制是指只仅允许在表的一端进行插入和删除操作,这一端被称为栈顶(Top),相对地,把另一端称为栈底(Bottom)。把新元素放到栈顶元素的上面,使之成为新的栈顶元素称作进栈、入栈或压栈(Push);把栈顶元素删除,使其相邻的元素成为新的栈顶元素称作出栈或退栈(Pop)。这种受限的运算使栈拥有“先进后出”的特性(First In Last Out),简称 FILO。
栈分顺序栈和链式栈两种。栈是一种线性结构,所以可以使用数组或链表(单向链表、双向链表或循环链表)作为底层数据结构。使用数组实现的栈叫做顺序栈,使用链表实现的栈叫做链式栈,二者的区别是顺序栈中的元素地址连续,链式栈中的元素地址不连续。
3.2. 堆简介
堆是一种常用的树形结构,是一种特殊的完全二叉树,当且仅当满足所有节点的值总是不大于或不小于其父节点的值的完全二叉树被称之为堆。堆的这一特性称之为堆序性。因此,在一个堆中,根节点是最大(或最小)节点。如果根节点最小,称之为小顶堆(或小根堆),如果根节点最大,称之为大顶堆(或大根堆)。堆的左右孩子没有大小的顺序。下面是一个小顶堆示例:
堆的存储一般都用数组来存储堆