目录
一、栈的概念及结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。
栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则
压栈 :栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
出栈 :栈的删除操作叫做出栈,出数据也在栈顶
栈遵循**后进先出,**可以理解为弹夹里的子弹,后装入的先打出去
二、栈的实现
栈的实现一般可以使用 数组或者链表实现, 相对而言数组的结构实现更优一些**。因为栈只会在一端进行插入和删除操作** ,用数组效率还是比较高,数组在尾上插入数据的代价比较小。当然,也会存在一些问题,就是每次空间不够,要重新开辟空间,可能会造成一些内存浪费。
栈的顺序储存结构
数组的首元素作为栈底,另外一端作为栈顶,同时定义一个变量 top 来记录栈顶元素在数组中的位置
栈的链表存储结构
单链表的尾部作为栈底,头部作为栈顶,方便插入和删除(进栈头插,出栈头删),头指针和栈顶指针 top 合二为一
三、栈的实现代码
要实现一个栈,我们先梳理一下基本结构,我们还是分两个源文件 "text.c(测试),Stack.c(函数的定义) "和一个头文件(Stack.h)函数的声明.
静态栈在现实中并没有动态栈实用,所以我主要讲一下动态栈
函数的定义和声明
cpp
// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
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* pst);
// 入栈
void StackPush(Stack* pst, STDataType data);
// 出栈
void StackPop(Stack* pst);
// 获取栈顶元素
STDataType StackTop(Stack* pst);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* pst);
// 销毁栈
void StackDestroy(Stack* pst);
栈的初始化
cpp
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->top = 0;//top指向栈顶数据的下一个
//ps->top = -1; // 意味着top指向栈顶数据
pst->capacity = 0;
}
栈的销毁
cpp
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = pst->capacity = 0;
}
入栈
cpp
void STPush(ST* pst)
{
assert(pst);
if(pst->top == pst->capacity)//检查栈空间是否满了
{
int newcapacity = pst->capacity == 0 ? 4 pst->capacity * 2;
STDataType* tmp = (STDataType*)realloc(pst->a,newcapacity * sizeof(STDataType);// 扩容至新容量
if(tmp == 0)
{
perror("realloc fail");
return;
}
pst->a = tmp;
pst->capacity = newcapacity; // 更新容量
}
pst->a[pst->top] = x; // 将新增元素放入栈顶空间
pst->top++;// 栈顶指针加一
}
删除数据
cpp
void STPop(SL* pst)
{
assert(pst);
assert(pst->top > 0); //栈不能为空
pst->top--; // 栈顶指针减一,相当于直接覆盖元素
}
获取栈顶元素
cpp
STDataType STTop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
return pst->a[pst->top - 1];
}
判空
cpp
bool SREmpty(ST* pst)
{
assert(pst);
return pst->top == 0; //看top是否变回初始化的值
}
获取栈中有效元素个数
cpp
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
四、代码整合
Stack.h
cpp
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef struct Stack
{
STDataType a[N];
int top; // 栈顶
}Stack;
// 初始化和销毁
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);
Stac.c
cpp
#include"Stack.h"
// 初始化和销毁
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
// top指向栈顶数据的下一个位置
pst->top = 0;
pst->capacity = 0;
}
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = pst->capacity = 0;
}
// 入栈 出栈
void STPush(ST* pst, STDataType x)
{
assert(pst);
// 扩容
if (pst->top == pst->capacity)
{
int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* tmp = (STDataType*)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++;
}
void STPop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
pst->top--;
}
// 取栈顶数据
STDataType STTop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
return pst->a[pst->top - 1];
}
// 判空
bool STEmpty(ST* pst)
{
assert(pst);
return pst->top == 0;
}
// 获取数据个数
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
text.c
cpp
#include"Stack.h"
int main()
{
// 入栈:1 2 3 4
// 出栈:4 3 2 1 / 2 4 3 1
ST s;
STInit(&s);
STPush(&s, 1);
STPush(&s, 2);
STPush(&s, 3);
STPush(&s, 4);
printf("%d ", STTop(&s));
STPop(&s);
STPush(&s, 5);
STPush(&s, 6);
while (!STEmpty(&s))
{
printf("%d ", STTop(&s));
STPop(&s);
}
STDestroy(&s);
}
本篇到这里就结束了,如有问题欢迎在评论区指正!
个人主页:uyeonashi-CSDN博客