• 数据结构之栈


    片头

    嗨! 小伙伴们,大家好! 今天我们来一起学习栈这个数据结构吧! 准备好了吗? 我要开始咯!

    一、栈

    1.1 栈的基本概念

    栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除操作。进入数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。我们可以想象成吃羊肉串,最先穿进去的羊肉块是被压在最下面最后一个羊肉块是在最上面的。

    压栈:栈的插入操作叫做进栈/压栈/入栈,从栈顶插入数据

    出栈:栈的删除操作叫做出栈,出数据也在栈顶

    1.2 栈的实现

    栈的实现一般可以通过用数组实现栈或者用链表实现栈,二者取其优,相对而言使用数组结构实现栈更简便高效。

    因为在前面顺序表的增删改查接口实现中(数据结构之顺序表)我们使用数组的结构来尾插尾删十分的方便,所以在栈的实现中我们把数组尾部定义为栈顶,头部定义成栈底即可。


    二、栈的接口实现

    栈和顺序表一样,可以设计成定长的静态栈或者动态增长的栈。因为定长栈局限性大,实际中不实用,所以我们主要实现支持动态增长的栈

    和前面的顺序表/链表接口实现相同,我们先创建一个头文件"Stack.h"和2个源文件"Stack.c" 和"Test.c",具体的作用为:

    Stack.h栈的定义,头文件的引用和接口函数的声明
    Stack.c接口函数的实现
    Test.c测试各个函数

    我们先展示"Stack.h" 的完整代码,不要忘记在2个源文件中引用"Stack.h"

    1. #pragma once //防止头文件被二次引用
    2. #include
    3. #include
    4. #include
    5. typedef int ElemType; //如果要修改存储的数据类型可直接在此修改
    6. typedef struct Stack {
    7. ElemType* arr; //动态数组
    8. int top; //栈顶
    9. int capacity; //容量
    10. }Stack;
    11. void StackInit(Stack* ps);//初始化栈
    12. void StackPush(Stack* ps, ElemType x);//入栈
    13. void StackPop(Stack* ps);//出栈
    14. ElemType StackTop(Stack* ps);//获取栈顶元素
    15. int StackSize(Stack* ps);//获取栈中有效元素的个数
    16. int StackEmpty(Stack* ps);//检测栈是否为空,如果为空返回非零结果,如果不为空返回0
    17. void StackDestroy(Stack* ps);//销毁栈

    其中,"top"的含义是由初始数值决定的,下面会细讲。接下来我们开始实现接口。

    (1)初始化栈
    1. //初始化栈
    2. void StackInit(Stack* ps) {
    3. assert(ps); //断言,防止传入空指针
    4. ps->arr = NULL; //初始化数组,置空
    5. ps->capacity = 0;//top指向栈顶元素的下一个位置
    6. ps->top = 0; //初始化容量
    7. }

    为了方便理解,我们将结构体中的top近似理解为数组的下标。如果我们在初始化栈时将top初始化为0,此时栈中没有数据,top指向栈顶数据的下一个位置

    如果我们将top初始化为-1时,top则会指向栈顶数据的位置。这里我们初始化成0更好,因为方便添加元素和删除元素。

    (2)入栈
    1. //入栈
    2. void StackPush(Stack* ps, ElemType x) {
    3. //扩容
    4. if (ps->capacity == ps->top) //容量已满,需要扩容
    5. {
    6. //如果容量为0,则扩容到4; 否则扩大2
    7. int newCapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);
    8. //创建一个临时指针变量来存储新空间地址,防止开辟失败
    9. ElemType* temp = realloc(ps->arr, newCapacity * sizeof(ElemType));
    10. if (temp == NULL) //防止开辟失败出现空指针
    11. {
    12. perror("realloc fail!\n");
    13. exit(1);
    14. }
    15. ps->arr = temp; //将临时指针变量中存放的新空间地址赋给arr
    16. ps->capacity = newCapacity;//空间容量更新
    17. }
    18. ps->arr[ps->top] = x;//将数据存放进栈顶元素的下一个位置
    19. ps->top++;//位置更新
    20. }

      因为栈和顺序表有差别,不能直接遍历打印,因此我们要打印栈中的元素,需要使用 StackEmpty函数 和 StackPop函数, 后面会讲到。

    (3)出栈
    1. //出栈
    2. void StackPop(Stack* ps) {
    3. assert(ps); //断言,防止传入空指针
    4. assert(ps->top); //断言,防止栈中没有元素,却还在执行删除
    5. ps->top--; //top指针往前挪动一位(相当于这个位置被覆盖了)
    6. }
    (4)获取栈顶元素
    1. //获取栈顶元素
    2. ElemType StackTop(Stack* ps) {
    3. assert(ps); //断言,防止传入空指针
    4. assert(ps->top); //断言,防止栈为空
    5. return ps->arr[ps->top - 1];//top-1为栈顶元素的位置,返回其值
    6. }
    (5)获取栈中有效的元素个数
    1. //获取栈中有效元素的个数
    2. int StackSize(Stack* ps) {
    3. assert(ps); //断言,防止传入空指针
    4. return ps->top; //top即为有效元素的个数
    5. }
    (6) 检测栈是否为空
    1. //检测栈是否为空,如果为空返回非零结果,如果不为空返回0
    2. int StackEmpty(Stack* ps) {
    3. assert(ps); //断言,防止传入空指针
    4. return ps->top == 0; //如果top==0, 说明栈为空
    5. }

    这就是为什么前面断言中的StackEmpty要加逻辑取反操作符的原因,如果栈为空,StackEmpty返回true,取反为false才能证明栈里面有元素。

    (7)销毁栈
    1. //销毁栈
    2. void StackDestroy(Stack* ps) {
    3. assert(ps); //断言,防止传入空指针
    4. if (ps->arr) //如果动态数组有效
    5. {
    6. free(ps->arr); //释放arr
    7. ps->arr = NULL; //将arr置空
    8. }
    9. ps->capacity = 0; //数组的容量为0
    10. ps->top = 0; //数组的栈顶top0
    11. }

    所有接口都完成后,我们在Test.c中测试一下代码:

    我们再多测试一下:

    完全没问题,恭喜你完成了栈的接口实现!

    片尾

    今天我们学习了栈这个数据结构,是不是比链表简单多了? 哈哈哈哈哈,希望看完这篇文章能对友友们有所帮助 !   !   !

    点赞收藏加关注 !   !   !

    谢谢大家 !   !   !

  • 相关阅读:
    SpringBoot:使用Caffeine实现缓存
    ZLToolKit网络库的自问自答
    点击试剂Methyltetrazine-PEG4-NHS ester,甲基四嗪-PEG4-琥珀酰亚胺酯,CAS:1802907-9
    『精华文稿』基于NeRF的三维内容生成
    Jenkins Jenkinsfile管理 Pipeline script from SCM
    【python】(五)python函数和python匿名函数lambda
    gin实现event stream
    在vue2中使用饼状图
    Spring整合第三方框架的两种方案(XML方式)
    C语言解题——指针解析(牛客网题目)
  • 原文地址:https://blog.csdn.net/qq_74336191/article/details/138155270