什么是栈?
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
(懒得画图.....直接在百度里找qaq)
栈的结构体定义以及函数声明
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的 代价比较小
——所以栈的实现也可以看做一个顺序表,只不过增添元素和删除元素的方式是不一样的。
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;//顶部数据
int capacity;//容量
}ST;
void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst,STDataType x);//顶部入栈,从顶部插入数据
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
因此结构体定义的* a指针 就是指向一段动态开辟的数组。
栈的元素插入
void STPush(ST* pst, STDataType x)
{
if (pst->top == pst->capacity)
{
int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;//给的是个数,若为空,则第一次给四个空间,否则就将空间扩大至两倍
STDataType* tmp = realloc(pst->a, newCapacity * sizeof(STDataType));//扩容后的指针
if (tmp == NULL)
{
perror("realloc fail");
return;
}
pst->a = tmp;
pst->capacity = newCapacity;//扩容后的容量
}
pst->a[pst->top] = x;//pst->top代表下标,此处表示在下标为top处的元素加入数据
pst->top++;
}
插入的思想和顺序表里有些许类似,也是要先获取容量是否超出,top其实就是数据量。并且top定义的是最后一个数据的位置。
那么每次插入数据后,仅需要把top++,并且赋值即可。
栈的大小
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
栈顶元素
STDataType STTop(ST* pst) //读取最顶处的数据
{
assert(pst);
assert(!STEmpty(pst));//不为空才读取,否则就会直接结束
return pst->a[pst->top-1];//读取
}
栈顶元素的删除
void STPop(ST* pst)//删除数据,仅有尾删,因为已经规定好入栈的顺序了,出栈的顺序也是固定的
{
assert(pst);
assert(pst->a);
assert(!STEmpty(pst));//栈不能为空
pst->top--;
}
判断是否栈是否为空
bool STEmpty(ST* pst)//仅判断大小是否为0即可。
{
assert(pst);
return pst->top == 0;
}
栈的删除
void STDestroy(ST* pst)//这是一个数组
{
assert(pst);
free(pst->a);//指针置为空
pst->a = NULL;
pst->top = pst->capacity = 0;//栈顶元素都设置为0
}
栈的初始化
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->top = 0;//为0时,指向栈顶元素的后一个位置,那么载入数据就是先放数据再将top位置往后移
//pst->top = -1;//指向栈顶元素,那么载入数据就要先将top++,再进行数据的载入
//故选择top为-1是比较好,可以判断此时栈里是否有元素,判断top是否为栈顶元素,且可以通过下标来表示
pst->capacity = 0;//初次的元素量(容量)为0
}
栈的实现的解释比较少,因为这是在顺序表的基础上实现的,然后数据的插入之类的都和顺序表类似,搞懂顺序表的实现,栈的实现也就会变得十分容易。