目录
1.栈的概念及结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶
对比顺序表和链表存储数据可以在头或者尾或者随时存在中间都是可以比较自由没有存储数据的要求,想正着访问倒着访问中间访问都可以,但栈是在这些基础上加了个紧箍咒,它要求在它里面存的数据要符合后进先出(或者可以说是先进后出
这个栈和系统中的栈是不一样的
一个是数据结构中的栈,是一个数据结构
一个是操作系统中内存划分的一个区域,叫做栈,用来函数调用时,建立栈帧
但是它们的行为是有一些相似的,都是先进后出
它们没有特别关系,属于两个学科
比如内存的堆和数据结构的堆就不一样 数据结构的堆是二叉树 内存的堆就是内存
栈的进栈顺序和出栈顺序
2.栈的实现
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。
因为数组在尾上插入数据的代价比较小。
2.1定义栈体结构(支持动态增长的栈)
typedef int STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶
int _capacity; // 容量
}Stack;
2.2初始化栈/销毁栈
初始化函数声明
void StackInit(Stack* ps);
初始化函数
void StackInit(Stack* ps)
{
ps->a = NULL;
ps->top = -1;
ps->capacity = 0;
}
销毁函数声明
void StackDestroy(Stack* ps);
销毁函数
void StackDestroy(Stack* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = -1;
ps->capacity = 0;
}
2.3入栈出栈
入栈实现思想
把栈顶设置为-1,每次入栈数据把栈顶+1 然后放入数据,保障栈顶随时在栈的最后一位入数据的地方
如果栈为空,没有数据那么就开辟4个数据空间给栈,如果栈中的容量满了,那么就扩容双倍容量提供后续栈数据放入
入栈代码
入栈函数声明
void StackPush(Stack*ps, STDataType);
入栈函数
void StackPush(Stack*ps, STDataType data)
{
assert(ps);
//判断数组是否为空/满数组,如果是则开辟/扩容
if(ps->capacity == ps->top+1)
{
size_t newcapacity = ps->capacity == 0 ? 4:ps->capacity*2;
STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType)*newcapacity);
if(!tmp)
{
printf("%s",There is an error in realloc);
exit(-1);
}
ps->a = tmp;
ps->capacity = newcapacity;
tmp = NULL;
}
ps->a[ps->top+1] = data;
ps->top++;
}
出栈实现思想
出栈显得更加简单,先前入栈是标记了栈顶的实时位置,那么出栈只需要把栈顶位置-1即可出栈
出栈代码
出栈函数声明
void StackPop(Stack*ps);
出栈函数
void StackPop(Stack*ps)
{
assert(ps);
if(ps->top > -1);
{
ps->top--;
}
}
2.4 获取栈顶元素与栈中有效元素个数
获取栈顶元素与有效个数实现思想
获取栈顶元素:由于我们在栈体结构中就有设置一个top单位专门用于标记栈顶所在位置,所以只需直接返回top即可
获取栈元素有效个数:由于数组是由0开始,所以数组中实际个数是由最后一个元素下标位置+1就是实际数字,而在栈中栈顶则是所有数据中的最后进入的一个元素 结构中的top则是栈顶的位置,所以只要返回top+1就是栈中有效的元素个数
获取栈顶元素函数
获取栈顶元素函数声明
STDataType StackTop(Stack* ps);
获取栈顶元素函数
STDataType StackTop(Stack* ps)
{
assert(ps);
if(ps->top != -1)
return ps->top;
}
获取栈中有效元素个数函数
获取栈中有效元素个数函数声明
int StackSize(Stack* ps);
获取栈中有效元素个数函数实现
int StackSize(Stack* ps)
{
assetr(ps);
//这里就是为什么原本要设置ps为-1的原因
//如果栈为空,那么top就是-1 +1就等于0返回
//如果不为空 top+1返回实际个数
return ps->top+1;
}
2.5 检测栈是否为空
检测栈是否为空实现思想
检测栈是否为空更加简单,判断top是否等于-1即可
检测栈是否为空实现函数
检测栈是否为空函数声明
int StackEmpty(Stack* ps);
检测栈是否为空函数实现
int StackEmpty(Stack* ps)
{
assert(ps);
//如果为空返回0,不为空返回1;
if(ps->top == -1)
return 0;
//走到这里就是不为空,返回1
return 1
}