栈 - 严蔚敏.吴伟民 版本
栈
栈 是限定仅在表尾进行插入和删除操作的线性表。
我们把允许插入和删除的一端称为栈顶(Top),另一端称为栈底(Bottom),不含任何数据元素的栈称为空栈。栈又称后进先出的线性表简称LIFO(Last in First out)结构。
定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指栈顶而不是栈底。它的特殊之处就在于限制了这个线性表的插入和删除位置,它始终只在栈顶进行。这也就使得:栈底是固定的,最先进栈的只能在栈底。
栈的插入操作(Push)叫做进栈,也称压栈、入栈。类似子弹入弹夹。
栈的删除操作(Pop)叫做出栈,也有叫弹栈。如同弹夹中的子弹出夹。
既然栈是线性表的特例,那么栈的顺序存储其实也是线性表顺序存储的简化,我们称为顺序栈。
顺序栈,即栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时符设指针top指示栈顶元素在顺序栈中的位置。通常习惯做法是以top=0表示空栈。
最开始栈中不包含任何数据,称为空栈,此时栈顶就是栈底。然后数据从栈顶进入,栈顶和栈底分离,整个栈的当前容量变大。数据出栈时从栈顶弹出,栈顶下移,整个栈的当前容量变小。
栈的结构定义
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef struct { int *base; //base指向栈底的指针变量 int *top; //top指向栈顶的指针变量 int stacksize; //栈的当前已分配的存储空间 }SqStack;
1.构造一个空栈
void InitStack(SqStack *s) { s->base = (int *)malloc( STACK_INIT_SIZE * sizeof(int *) ); if (!s->base) exit(0); //存储分配失败 s->top = s->base; //最开始 栈顶就是栈底 s->stacksize = STACK_INIT_SIZE; //空栈的可用空间100 }
2.入栈 插入元素e为新的栈顶元素
void Push(SqStack *s, int e) { if (s->top - s->base >= s->stacksize) //栈满 追加空间 { s->base = (int *)realloc(s->base, (s->stacksize + STACKINCREMENT) * sizeof(int)); if (!s->base) exit(0); s->top = s->base + s->stacksize; //设置栈顶 s->stacksize = s->stacksize + STACKINCREMENT; //设置栈的最大容量 } *(s->top) = e; s->top++; }
3.出栈 若栈不空则删除栈s的栈顶元素 用e返回
void Pop(SqStack *s, int *e) { if (s->top = s->base) //栈空 return; *e = *--(s->top); }
4.清空栈 清空一个栈就是将栈中的元素全部作废但栈本身物理空间并不发生改变(不是销毁)
void ClearStack(SqStack *s) { s->top = s->base; }
5.销毁栈 销毁一个栈是要释放该栈所占据的物理内存空间
void DestroyStack(SqStack *s) { int i, len; len = s->stacksize; for (i = 0;i < len;i++) { free(s->base); s->base++; } s->base = s->top = NULL; s->stacksize = 0; }
6.计算栈的当前容量 也就是计算栈中元素的个数,因此返回s->top - s->base即可。
栈的最大容量是指该栈占据内存空间的大小,其值是s->stacksize
int StackLen(SqStack s) { return (s.top - s.base); }