1.1栈的概念及结构
一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
特点: 后进后出(Last In First Out)
进栈出栈示意图::
1.2栈的实现
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的 代价比较小。
观察以上三种结构,可以发现双向链表是比较复杂的,因为使用单链表进行头插就可以满足栈的实现,但是由于数组具有高效缓存的特点,因此栈的实现选择数组更好一点。
// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
typedef int STDataType;
#define N 10
typedef struct Stack
{
STDataType _a[N];
int _top; // 栈顶
}Stack;
// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶
int _capacity; // 容量
}Stack;
// 初始化栈
void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);
接下来将一一演示代码的实现
以vs2022进行演示,先是创建了 Stack.h Stack.c 和 test.c 一个头文件和两个 .c 文件
//包含的头文件有
#include <stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//动态栈
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
由于静态栈使用较少,所以用动态栈展示。
1.2.1 栈的初始化
//Stack.h
//初始化
void STInit(ST* pst);
//Stack.c
//初始化
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->capacity = pst->top = 0;
}
进行调试发现,栈初始化成功。
后续操作与初始化一致,所以就单独将 Stack.c 里面代码展示。
1.2.2 栈的销毁
//销毁
void STDestory(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = pst->top = 0;
}
1.2.3 入栈
void STPush(ST* pst, STDataType x)
{
assert(pst);
//判断空间够不够
if (pst->capacity == pst->top)
{
//空间不够,需要申请一片空间
int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
if (tmp == NULL)
{
perror("mealloc fail!");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top] = x;
pst->top++;
}
因为栈的定义就已经限制了栈只可以一端进栈,所以就不用区分头插和尾插,
1.2.4 删除元素
//删除
void STPop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
pst->top--;
}
删除元素时,要注意不仅栈的地址不能为空,并且里面的元素也不可以为空。
1.2.5 判空
bool STEmpty(ST* pst)
{
assert(pst);
return pst->top == 0;
}
如果 pst->top == 0,就为真
1.2.6 获取栈顶元素
STDataType STTop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
return pst->a[pst->top - 1];
}
1.2.7 获取元素个数
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
1.3 栈打印
是不是看了以上代码演示,觉得为什么会有一个bool类型呢?接下来就将为大家展示一下bool这个判空函数的使用方法。
#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
int main()
{
ST st;
STInit(&st);
STPush(&st, 1);
STPush(&st, 2);
STPush(&st, 3);
STPush(&st, 4);
while (!STEmpty(&st))
{
printf("%d ", STTop(&st));
STPop(&st);
}
printf("\n");
STDestory(&st);
return 0;
}
以上就是栈的基本内容以及操作了,下一期将为大家带来队列的内容。