实现一个可以自动增长的顺序栈,结构体中需要包含栈头,栈顶指针(指向当前可以存放数据的位置),栈的总大小(记录大小,方便栈的扩容)
#define INITSIZE 10
typedef char ElemType;
typedef struct Stack
{
ElemType* base;//头,不动的
ElemType* top;//栈顶指针,指向当前可以存放数据的位置,p是下标,*p是数据
int stacksize;//总大小
}Stack, * PStack;//PStack==Stack*
初始化
顺序栈的初始化给头申请空间,栈顶指针一开始指向头,总大小即为初始设定的INITSIZE。
void InitStack(PStack ps)
{
assert(ps != NULL);
ps->base = (ElemType*)malloc(INITSIZE * sizeof(ElemType));
assert(ps->base != NULL);
if (ps == NULL)
return;
ps->top = ps->base;
ps->stacksize = INITSIZE;
}
扩容
若栈顶指针等于头的位置加上总大小的长度的位置则栈满,此时需要用realloc扩容,扩容后必须重新赋值:即ps->top = ps->base+ps->stacksize。因为扩容后栈的位置(地址)可能会改变,不是原来栈顶指针指向的地方了。
static bool IsFull(PStack ps)
{
return ps->base + ps->stacksize == ps->top;
}
//扩容函数(扩大到原来容量的2倍),内部函数
static void Inc(PStack ps)
{
ps->base = (ElemType*)realloc(ps->base, 2 * ps->stacksize * sizeof(ElemType));
assert(ps->base != NULL);
if (ps->base == NULL)
{
perror("扩容失败");//输出错误信息
return;
}
ps->top = ps->base + ps->stacksize;//必须重新赋值
ps->stacksize *= 2;
}
入栈:给栈顶元素赋值,然后top++
出栈
出栈函数需要传入两个参数,一个是栈,另一个是一个ElemType类型的指针,用来存放传出的值。不能用函数返回值返回参数,因为如果栈为空,返回任何值都不合适(任何值都有可能是栈内元素的类型)。
//获取栈顶元素,且删除栈顶元素
bool Pop(PStack ps, ElemType* rtval)
{
if (IsEmpty(ps))
return false;
*rtval = *(--ps->top);
return true;
}
//获取栈顶元素,但不删除
bool GetTop(PStack ps, ElemType* rtval)
{
if (IsEmpty(ps))
return false;
*rtval = *(ps->top - 1);
return true;
}
求栈的长度直接top-base
如果top==base则为空
top=base是清空栈的方式
销毁栈
ps->base是个指针,所以需要free,让它指向空防止free多次
//销毁栈
void Destroy(PStack ps)
{
free(ps->base);
ps->base = NULL;
ps->top = NULL;//(*ps).top = NULL;
ps->stacksize = 0;
//ps = NULL;//没有意义
}