基本概念
栈的顺序存储结构称为顺序栈
使用数组作为顺序栈存储方式的特点:简单方便单容易产生溢出(数组大小固定)
- 上溢:栈已经满,还要压入元素
- 下溢:栈已经空,还要弹出元素
上溢一般认为是一种错误,使问题的处理无法进行,而下溢一般认为是一种结束条件,即问题处理结束。
栈顶指针
top 栈顶指针,指示栈顶元素在顺序栈中的位置。但是一般为了方便,通常 top 指向栈顶元素之上的下标位置。
栈底指针
base 栈底指针,指示栈底元素在顺序栈中的位置,在栈构造之前和销毁之后,base 的值为 NULL
栈空
base 栈底指针 = top 栈顶指针
入栈
代码实现
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
// 函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
typedef int Status; // Status 是函数的类型,其值是函数结果状态代码,如 OK 等
typedef int Boolean; // Boolean 是布尔类型,其值是 TRUE 或 FALSE
typedef int SElemType; // 定义栈元素类型为整型
#define STACK_INIT_SIZE 10 // 存储空间初始分配量
#define STACK_INCREMENT 2 // 存储空间分配增量
typedef struct SqStack
{
SElemType *top; // top 栈顶指针,指示栈顶元素在顺序栈中的位置。但是一般为了方便,通常 top 指向栈顶元素之上的下标位置。
SElemType *base; // base 栈底指针,指示栈底元素在顺序栈中的位置,在栈构造之前和销毁之后,base 的值为 NULL
int stacksize; // 当前已分配的存储空间,以元素为单位
} SqStack; // 定义一个顺序栈数据类型
// 顺序栈的基本操作(9个)
/* 初始化操作 */
void InitStack(SqStack *S)
{ // 操作结果:构造一个空栈 S
S->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!(S->base))
exit(-1); // 存储分配失败
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
return;
}
/* 销毁栈操作 */
void DestroyStack(SqStack *S)
{ // 初始条件:栈 S 已经存在
// 操作结果:销毁栈 S,S 不再存在
free(S->base);
S->base = NULL;
S->top = NULL;
S->stacksize = 0;
return;
}
/* 栈置空操作 */
void ClearStack(SqStack *S)
{ // 初始条件:
// 操作结果:把 S 置为空栈
if (S->base)
S->top = S->base;
return;
}
/* 判断 S 是否为空
空栈:base == top 是栈空标志
*/
Status StackEmpty(SqStack S)
{ // 初始条件:栈 S 已经存在
// 操作结果:若栈 S 为空栈,则返回 TRUE,否则返回 FALSE
if (S.top == S.base)
return TRUE;
else
return FALSE;
}
/* 求栈的长度 */
int StackLength(SqStack S)
{ // 初始条件:栈 S 已经存在
// 操作结果:返回 S 的元素个数,即栈的长度
return S.top - S.base;
}
/* 获取栈顶元素 */
Status GetTop(SqStack S, SElemType *e)
{ // 初始条件:栈 S 已经存在
// 操作结果: 若栈不空,则用 e 返回 S 的栈顶元素,并返回 OK;否则返回 ERROR
if (S.top > S.base)
{
*e = *(S.top - 1);
return OK;
}
else
{
return ERROR;
}
}
/* 入栈操作
栈满:top - base == stacksize
算法思路:
1、判断是否满栈
2、元素 e 压入栈顶元素
3、栈顶指针加 1
*/
void Push(SqStack *S, SElemType e)
{ // 初始条件:栈 S 已经存在
// 操作结果:插入元素 e 为新的栈顶元素
if (S->top - S->base >= S->stacksize) // 栈满,追加存储空间
{
S->base = (SElemType *)realloc(S->base, (S->stacksize + STACK_INCREMENT) * sizeof(SElemType));
if (!(S->base))
exit(-1); // 存储分配失败
S->top = S->base + S->stacksize;
S->stacksize += STACK_INCREMENT;
}
*(S->top)++ = e;
}
/* 出栈操作
栈空:top == base 下溢
算法思路:
1、判断是否栈空
2、栈顶指针减 1
3、获取栈定元素
*/
Status Pop(SqStack *S, SElemType *e)
{ // 初始条件:栈 S 已经存在
// 操作结果: 若栈不空,则删除 S 的栈顶元素,用 e 返回其值,并返回 OK;否则返回 ERROR
if (S->top == S->base)
return ERROR;
*e = *--(S->top);
return OK;
}
/* 遍历栈 */
void StackTraverse(SqStack S, void (*visit)(SElemType))
{ // 初始条件:栈 S 已经存在
// 操作结果:从栈底到栈顶依次对栈中每个元素调用函数 visit()
while (S.top > S.base)
visit(*S.base++);
printf("\n");
}
void main(int argc, char *argv[])
{
int j;
SqStack s;
SElemType e;
InitStack(&s); // 初始化栈s
for (j = 1; j <= 5; j++) // 将2,4,6,8,10入栈
Push(&s, 2 * j);
Pop(&s, &e);
printf("pop stack is %d\n", e);
GetTop(s, &e);
printf("top value is %d\n", e);
Pop(&s, &e);
printf("pop stack is %d\n", e);
GetTop(s, &e);
printf("top value is %d\n", e);
}
/*
编译:gcc test.c -o test
运行:./test
结果:
pop stack is 10
top value is 8
pop stack is 8
top value is 6
*/
/********************* end of file ******************************/