文章目录
一、栈(后进先出,LIFO表)
定义:限定仅在表尾进行插入或删除操作的线性表。表尾为栈顶,表头为栈底,不含元素的空表称为空栈。
最先放入栈中元素在栈底,最后放入的元素在栈顶;而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除。
二、栈的用途
栈(操作系统):由编译器自动分配释放,存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈,栈使用的是一级缓存,他们通常都是被调用时处于存储空间中,调用完毕立即释放。
堆(操作系统):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定。
一个由C/C++编译的程序占用的内存分为以下几个部分:
·栈区(stack)——由编译器自动分配释放,存放函数的参数名、局部变量的名等。其操作方式类似于数据结构中的栈。
·堆区(heap)——由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
·全局区(静态区)(static)——全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
·文字常量区——常量字符串就是放在这里的,程序结束后由系统释放。
·程序代码区——存放函数体的二进制代码。
标注:堆和栈可以分为两种,一种是数据结构中的堆栈,另一种是和内存的分配有关,这里写的是内存分配中的堆栈。这两种虽然都有堆和栈,但是两者关系并不大。
1.栈、堆是数据结构里面的叫法。
2.堆区、栈区则是内存模型的叫法。
三、栈的表示和实现
(为了表示方便,所有数据定义为int型,使用时可替换。)
1.栈的顺序存储
(1)顺序栈
栈的顺序存储结构简称为顺序栈,它是运算受限的顺序表。因此,可以用一组连续的存储单元(数组)依次存放栈中的每个数据元素来实现顺序栈。因为栈底位置是固定不变的,所以可以将栈底位置设置在数组的两端的的任何一个端点。
用下标变量记录栈顶的位置,栈顶指针始终指向栈顶元素的上一个单元,用top(栈顶指针)表示。用base(栈底指针)记录栈底位置,为栈空间的起始位置。(类似于数组,top指针的位置为第一个无效的元素,top-1才是栈顶元素的位置指针)
栈的顺序存储表示:
#define INITSIZE 100//栈的存储空间初始分配量
typedef struct
{
int top;//栈顶指针
int *base;//栈底指针,存放空间起始地址
int stacksize;//当前栈空间的长度
}sqstack;
顺序栈中有“上溢”和“下溢”:
设S是sqstack类型的指针变量。若栈底位置在向量的低端,即S.base[0]是栈底元素,那么栈顶指针S.top是正向增加的,即进栈时需将S.top加1,退栈时需将S.top 减1。因此,S.top == 0时表示空栈, S.top == stacksize表示栈满。当栈满时再做进栈运算必定产生空间溢出,简称“上溢”;当栈空时再做退栈运算也将产生溢出,简称“下溢”。上溢是一种出错状态,应该设法避免之;下溢则可能是正常现象,因为栈在程序中使用时,其初态或终态都是空栈,所以下溢常常用来作为程序控制转移的条件。
(2)顺序栈上的基本操作实现
①初始化栈S(创建一个空栈S)
int initstack(sqstack *S)
{
S->base=(int*)malloc(INITSIZE*sizeof(int));
if(!S->base)return