栈
什么是栈
关于栈,在 如何使用两个栈实现一个队列 中粗略介绍过,下面将详细接受栈以及栈代码的实现。
栈 符合 先进后出,后进先出!——函数调用堆栈,类似于弹匣的结构。
栈底: 栈的存储空间的最底下的位置。一般是一块空间的首地址。
栈顶: 动态变化的位置,会随着入栈和出栈操作在申请的空间上左右滑动。
栈大小: 记录总共能够存储的数据元素的个数。
栈的代码实现
顺序栈的结构
typedef int ElemType;
typedef struct Stack
{
ElemType *stack_low; // 栈底指针,存储空间的首地址
int top; // 栈顶(使用下标来表示), 元素的个数
int size; // 栈空间的大小
}Stack;
顺序栈的操作方法
void InitStack(Stack *st, int init_size); // 初始化
bool Push(Stack *st, ElemType data); // 入栈
bool Top(Stack *st, ElemType *reval); // 仅仅获取栈顶的数据
bool Pop(Stack *st); // 出栈, 仅仅弹出栈顶的数据
bool Empty(Stack *st); // 判空
void DestroyStack(Stack *st); // 销毁
方法的实现
InitStack__栈的初始化
void InitStack(Stack *st, int init_size)
{
if(st == NULL) exit(0);
init_size = init_size > 0 ? init_size : 10;
st->stack_low = (ElemType*)malloc(sizeof(ElemType) * init_size);
//分配空间给栈使用
if(st->stack_low == NULL) exit(0);
st->top = 0;//栈顶为0,此时栈为空
st->size = init_size;
}
Push__入栈
其中调用了:判满函数,以及给栈增加空间函数
bool Push(Stack *st, ElemType value)
{
if(st == NULL) exit(0);
if(Full(st))
{
if(!AppendSpace(st))
{
return false;
}
}
st->stack_low[st->top++] = value;
//例如下图,向空栈中入栈a,则st->stack_low[0] = value
//而 st->top 正好为需要放入空间的下标 同时令top++ 就实现入栈
//则st->stack_low[0]中存放了a,而 tou == 1.
return true;
}
Full__判满
static bool Full(Stack *st)
{
return st->top == st->size;
//当top的下标等于size时 栈满
}
当栈满,top指向的下标大小 正好为 size 的大小
AppendSpace__增加空间
static bool AppendSpace(Stack *st)
{
ElemType *new_space = (ElemType*)malloc(sizeof(ElemType) * st->size * 2);
//申请双倍空间的 new_space
if(new_space == NULL) return false;
for(int i = 0; i < st->size; ++i)
{
new_space[i] = st->stack_low[i];
}//将原本的入栈数据放入new_space
free(st->stack_low);//释放原本的栈
st->stack_low = new_space;//指针指向新栈的地址
st->size *= 2;//size * 2
return true;
}
Top__获取栈顶数据
这里调用了:判空函数
bool Top(Stack *st, ElemType *reval)
{
if(st == NULL) exit(0);
if(Empty(st)) return false;
*reval = st->stack_low[st->top - 1];//给 *reval 赋值栈顶元素
return true;
}
Pop__弹出栈顶数据
bool Pop(Stack *st)
{
if(st == NULL) exit(0);
if(Empty(st)) return false;
st->top--;//判空后之间令top--,即使得原本栈最后一个数据变为栈顶(top)
return true;
}
这个时候栈内只有 a,b,c,d 四个数据,尽管stack_low[4]存放着d,但是不将它视为栈内数据。
Empty__判空
bool Empty(Stack *st)
{
if(st == NULL) exit(0);
return st->top == 0;//查看top是否为0即可
}
DestryStack__销毁栈
void DestroyStack(Stack *st)
{
if(st == NULL) exit(0);
free(st->stack_low);//直接释放顺序表空间
st->stack_low = NULL;
st->top = st->size = 0;
//清空数据即可
}
链式栈的实现
和链表的操作完全一样,除了初始化,销毁,判空, 头插(Push),头删(Pop)等方法。