栈是一种只能在一端进行插入和删除操作的特殊线性表,遵循后进先出原则。栈用来存储数据的结构一般是数组,因为电脑CPU需要数据时不会直接访问内存,而是访问高速缓冲存储器,访问时如果高速缓存中没有所需要的数据,高速缓存就会去内存中获取所需的数据,但是高速缓存并不仅仅拿取所需的数据,还会把所需数据后面的一段内存连续的内容都拿走(拿走是形象说法,其实是内存把数据复制一份给高速缓存),方便CPU下次取数据。链表的节点是不连续的,这样来看数组就要优于链表,所以栈采用数组存数据。
栈的基本操作包括入栈、出栈、统计栈中元素个数、判断栈是否为空和访问栈顶元素等,接下来我们将一一讨论。
使用数组存储数据,为了让数组空间能动态的申请,避免数组空间开大浪费,开小不够用,定义一个结构体类型。
typedef int STDataType;//给int一个新名字STDataType,之后都用STDataType,当栈中要存放其他类型的数据时,只要把这里的int改掉就就好了
#define InitSize 4//给数组的初始空间的大小,初始化的时候用
typedef struct Stack
{
STDataType* a;//数组指针
int top;//栈顶指针
int capacity;//数组容量
}ST;
该数据结构在使用之前要先初始化,否则数组指针是野指针,top和capacity里是随机值。
void STInit(ST* ps)//给函数传ST类型的变量的地址
{
assert(ps);
STDataType* tmp = (STDataType*)malloc(sizeof(STDataType) * InitSize);//申请4个STDataType类型的空间
if (tmp == NULL)//申请失败,直接报错返回
{
perror("malloc");//在屏幕上打印错误信息
return;
}
ps->a = tmp;//申请成功,赋值给数组指针
ps->top = 0;//top等于0,top指向栈顶元素下一个位置
//ps->top=-1;top等于-1,top指向栈顶元素
ps->capacity = InitSize;//初始容量等于4
}
入栈操作和把数据尾插到数组里相似,数据尾插可以访问任意元素,然后把数据插到数组最后面,但是入栈只能在一端进行操作,只能访问栈顶元素。插入之前最好检查一下数组是否还有空间,如果已经满了,就要扩大容量。
void STPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)//top和capacity大小相等时,数组就满了,要对数组扩容
{
STDataType* tmp = (STDataType*)realloc(ps->a , sizeof(STDataType) * ps->capacity * 2);//使用realloc重新申请空间,大小为原来的两倍
if (tmp == NULL)
{
perror("malloc");
return;
}
ps->a = tmp;
ps->capacity *= 2;//数组容量扩大到原来的两倍
}
ps->a[ps->top] = x;//把数据插入数组
ps->top++;//top往后走一个位置
}
出栈操作很简单,只要把栈顶指针往前挪一个位置就好,但是出栈前要看数组是否为空,数组为空表示栈中已经没有元素,不能再出栈。
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));//判断数组中是否还有元素,如果为空,就不能再删除
ps->top--;//栈顶指针往前走一个
}
统计栈中元素个数,只要看top就好,因为top指向栈顶元素的下一个位置。但是数组下标从0开始,所以top的大小就是元素的个数。
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
判断栈是否为空,只要top等于0,栈中就没有元素,为空。
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;//当top等于0时,表达式为真,返回true;top不等于0时,表达式为假,返回false
}
访问栈顶元素就是访问下标为top-1的元素,因为top指向栈顶元素的后一个位置。
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top - 1];
}
结束使用时,最好把开辟的空间销毁。
void STDestroy(ST* ps)
{
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
栈的基本操作差不多就这些了,如果有问题,欢迎指出和提问哦,嘿嘿~(¯▽¯~)!