栈的概念和结构
一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
例如实际中的弹夹,先进的子弹在最底端,且是最后打出去的
栈的实现
栈的实现分为链式栈(链表)和顺序栈(数组)
这里链式相比于数组来说,效率都差不多,但是数组的缓存命中率更高,所以使用数组(两种结构都差不多,数组稍微好一点)
代码实现
1.头文件等创建
#ifndef STACKQUEUE_H
#define STACKQUEUE_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int STDatatType;
typedef struct Stack
{
STDatatType* arr; 指针,用于接收申请动态内存返回的首地址
int top; 栈顶标志位
int capacity; 总容量
}ST;
#endif STACKQUEUE_H
2.相关接口函数
(1)初始化
void StackInit(ST* ps)
{
ps->arr = NULL;
ps->top = 0;
ps->capacity = 0;
}
(2)判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
(3)释放
void StackDestroy(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
free(ps->arr);
ps->arr = NULL;
ps->top = 0;
ps->capacity = 0;
}
(4)读取栈顶内容
STDatatType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->arr[ps->top-1];
}
(5)判断当前栈中大小
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
(6)入栈
void StackPush(ST* ps,STDatatType x)
{
assert(ps);
if(ps->capacity == ps->top)
{
int newcapacity = ps->capacity == 0? 4: ps->capacity*2;
STDatatType* temp = (STDatatType*)realloc(ps->arr,sizeof(STDatatType)*newcapacity);
if(temp == NULL)
{
perror("realloc");
exit(-1);
}
ps->arr = temp;
ps->capacity = newcapacity;
}
ps->arr[ps->top] = x;
ps->top++;
}
(7)出栈
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
由于是数组申请的动态内存,释放需要传首地址。所以这里模拟只把位置标志位减1,下次Push时覆盖其数据就可以,不会影响功能
最后写完的头文件
#ifndef STACKQUEUE_H
#define STACKQUEUE_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int STDatatType;
typedef struct Stack
{
STDatatType* arr;
int top;
int capacity;
}ST;
//初始化
void StackInit(ST* ps);
//栈为空返回真
int StackEmpty(ST* ps);
//当前栈的大小
int StackSize(ST* ps);
//入栈
void StackPush(ST* ps,STDatatType x);
//出栈
void StackPop(ST* ps);
//取栈顶内容
STDatatType StackTop(ST* ps);
//释放
void StackDestroy(ST* ps);
#endif STACKQUEUE_H
本篇的主要基础是顺序表,在顺序表的基础上模拟出栈的先进后出原则