4.4 栈的顺序存储结构及实现
4.4.1 栈的顺序存储结构
既然栈是线性表的特例,那么栈的顺序存储其实也是线性表顺序存储的简化,我们简称为顺序栈。线性表是用数组来实现的,想想看,对于栈这种只能一头插入删除的线性表来说,用数组哪一端来作为栈顶和栈底比较好?
对,没错,下标为0的一端作为栈底比较好,因为首元素都存在栈底,变化最小,所以让它作栈底。
我们定义一个top变量来指示栈顶元素在数组中的位置,这top就如同中学物理学过的游标卡尺的游标,如图4-4-1,它可以来回移动,意味着栈顶的top可以变大变小,但无论如何游标不能超出尺的长度。同理,若存储栈的长度为StackSize,则栈顶位置top必须小于StackSize。当栈存在一个元素时,top等于0,因此通常把空栈的判定条件定为top等于-1。

图4-4-1
来看栈的结构定义
- /* SElemType类型根据实际情况而定,这里假设为int */
- typedef int SElemType;
- typedef struct
- {
- SElemType data[MAXSIZE];
- /* 用于栈顶指针 */
- int top;
- }SqStack;
若现在有一个栈,StackSize是5,则栈普通情况、空栈和栈满的情况、空栈和栈满的情况示意图如图4-4-2所示。

图4-4-2
4.4.2 栈的顺序存储结构——进栈操作
对于栈的插入,即进栈操作,其实就是做了如图4-4-3所示的处理。

图4-4-3
因此对于进栈操作push,其代码如下:
- /* 插入元素e为新的栈顶元素 */
- Status Push(SqStack *S, SElemType e)
- {
- /* 栈满 */
- if (S->top == MAXSIZE - 1)
- {
- return ERROR;
- }
- /* 栈顶指针增加一 */
- S->top++;
- /* 将新插入元素赋值给栈顶空间 */
- S->data[S->top] = e;
- return OK;
- }
4.4.3 栈的顺序存储结构——出栈
操作
出栈操作pop,代码如下:
- /* 若栈不空,则删除S的栈顶元素,用e返回其值,
- 并返回OK;否则返回ERROR */
- Status Pop(SqStack *S, SElemType *e)
- {
- if (S->top == -1)
- return ERROR;
- /* 将要删除的栈顶元素赋值给e */
- *e = S->data[S->top];
- /* 栈顶指针减一 */
- S->top--;
- return OK;
- }
两者没有涉及到任何循环语句,因此时间复杂度均是O(1)。
