今天的内容是关于我们如何用数组来实现栈,我们先来看一下我们对栈的定义是什么
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
所以栈是满足先进后出的,我们把一个数据放入到栈中称为入栈,当我们从栈顶取出元素的时候,我们称这个操作就是出栈,我们如果用图来表示的话就是下面这个图
如果我们出栈的话也是在上面的栈顶进行出栈的,这就是栈的特点,这里要区分一个东西,这个是数据结构中的栈,而不是我们的函数栈帧的这个栈,还有就是我们的栈溢出不是指我们数据结构的栈数据满了,而是在栈上的时候我们这个栈满了,之前我们在C语言学习中的栈是用来存储局部变量这些东西的。
那今天我们就来用代码实现一个简单的栈。
首先我们和之前一样,先定义我们的结构体是个什么样子的
可以发现这个和我们之前认识的顺序表是不是差不多,就只是以前顺序表的时候我们的top是size,现在我们的top的含义就是指向我们这个栈的栈顶元素,但是我们之前就说过其实数据结构是没有一定的规定,我们的top这里也是可以表示这个数据的个数,那我们后面在实现接口函数要注意就就只有取栈顶的元素的时候要-1就行,我们这里top表示的就是栈顶的元素
那第一个函数就是我们对这个栈进行初始化,这里初始化的时候我们的top给的就是表示栈顶元素,那我们如果个top的值是0的话就会有问题,所以这里我们得从-1开始才是最合适的。
void Init(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->capacity = 0;
ps->top = -1;
}
这个就是我们的初始化函数的实现,其实初始化没什么需要注意的地方,下面我们再来实现我们的压栈,我们都知道压栈的时候如果空间不够的时候,就会出现问题,所以我们需要进行扩容,扩容的条件就是当我们top+1 == capacity的时候,就需要扩容, 扩容在我们的顺序表中有讲解这里就直接给大家看代码了。
void Push(ST* ps, STDateType x)
{
assert(ps);
if (ps->top + 1 == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDateType* tmp =(STDateType*) realloc(ps->a, sizeof(STDateType) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->capacity = newcapacity;
ps->a = tmp;
}
ps->top++;
ps->a[ps->top] = x;
}
这里我们push之后一定不能忘记++
有了扩容就有我们对空间进行释放,释放就是我们realloc出来的内存,我们这里就只要释放它就行,它是我们结构体的内容,我们用一级指针就可以进行解决了。
下面是代码
void Dstory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->capacity = 0;
}
入栈的代码写好之后我们就要些出栈,那出栈有什么值得我们需要注意的地方吗,首先我们这个栈不能为空吧,其次就是我们出栈就是把栈顶元素拿掉,就是我们的top,那我们直接–不就行了吗,因为下一次进来的时候只需要进行的操作就是入栈,入栈会覆盖上面的值。
void Pop(ST* ps)
{
assert(ps);
assert(ps->top >= 0);
ps->top--;
}
写完这些剩下的就是一些基本操作,我们直接来实现就行了
STDateType Top(ST* ps);
bool Empty(ST* ps);
int Size(ST* ps);
STDateType Top(ST* ps)
{
assert(ps);
return ps->a[ps->top];
}
bool Empty(ST* ps)
{
assert(ps);
return ps->top == -1;
}
int Size(ST* ps)
{
assert(ps);
return ps->top + 1;
}
那完整的代码以及测试的代码就放在下边了。
Stack.h
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int STDateType;
typedef struct Stack
{
STDateType* a;
int top;
int capacity;
}ST;
void Init(ST* ps);
void Push(ST* ps, STDateType x);
void Pop(ST* ps);
STDateType Top(ST* ps);
void Dstory(ST* ps);
bool Empty(ST* ps);
int Size(ST* ps);
#include"stack.h"
void Init(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->capacity = 0;
ps->top = -1;
}
void Push(ST* ps, STDateType x)
{
assert(ps);
if (ps->top + 1 == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDateType* tmp =(STDateType*) realloc(ps->a, sizeof(STDateType) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->capacity = newcapacity;
ps->a = tmp;
}
ps->top++;
ps->a[ps->top] = x;
}
void Pop(ST* ps)
{
assert(ps);
assert(ps->top >= 0);
ps->top--;
}
void Dstory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->capacity = 0;
}
STDateType Top(ST* ps)
{
assert(ps);
return ps->a[ps->top];
}
bool Empty(ST* ps)
{
assert(ps);
return ps->top == -1;
}
int Size(ST* ps)
{
assert(ps);
return ps->top + 1;
}
那今天的satck就分享到这里,我们下次再见。