• 【数据结构】C语言实现栈


    • 🎈个人主页:库库的里昂
    •  🎐C/C++领域新星创作者
    •  🎉欢迎 👍点赞✍评论⭐收藏
    • ✨收录专栏:数据结构与算法
    • 🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗

    前言

    在前几期的学习中,我们认识了顺序表和链表这两种线性表,而在本期学习中,我们将会认识别的线性表。跟随我们的脚本,看看栈和队列有怎样的特点。

    1. 栈

    1.1 栈的概念

    栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

    • 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
    • 出栈:栈的删除操作叫做出栈。出数据也在栈顶。

    1.2 栈的结构

    2. 栈的实现

    栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。

    2.1 栈的初始化

    我们将结构体的所有元素都初始化为0。这里与我们在顺序表中的初始化不同,在顺序表中我们在初始化时就开辟了空间,下面我们会介绍另一种方式。

    1. void STInit(ST* pst)
    2. {
    3. assert(pst);
    4. pst->a = NULL;
    5. pst->capacity = 0;
    6. pst->top = 0;
    7. }

    2.2 入栈

    在进栈时可能遇到容量为零,所以我们使用一个条件判断,来确定容量。因为top为0,所以它表示的是下一个元素的下标,要先赋值,再top++

    1. void STPush(ST* pst, STDataType x)
    2. {
    3. assert(pst);
    4. if (pst->top == pst->capacity)
    5. {
    6. int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
    7. STDataType* tmp = calloc(pst->a, sizeof(STDataType) * newcapacity);
    8. if (tmp == NULL)
    9. {
    10. perror("calloc fail");
    11. return;
    12. }
    13. pst->a = tmp;
    14. pst->capacity = newcapacity;
    15. }
    16. pst->a[pst->top] = x;
    17. pst->top++;
    18. }

    malloc 和 realloc 开辟空间的区别就是 realloc 要传递一个指针,而当我们给 realloc 传递一个空指针,那么它的功能就和 malloc 相同。 

    2.3 出栈 

    出栈只需要将 top --就访问不到这个元素了。在出栈时我们要判断栈中是否还有元素。

    1. void STPop(ST* pst)
    2. {
    3. assert(pst);
    4. assert(pst->top > 0);
    5. pst->top--;
    6. }

    2.4 读取栈顶元素

    栈顶元素就是我们插入的最后一个元素。由于top表示的是下一个元素的下标,所以读取栈顶元素是top要减1。

    1. STDataType STTop(ST* pst)
    2. {
    3. assert(pst);
    4. assert(pst->top > 0);
    5. return pst->a[pst->top - 1];
    6. }

    2.5 判断栈空

    1. bool STEmpty(ST* pst)
    2. {
    3. assert(pst);
    4. return pst->top == 0;
    5. }

    2.6栈的销毁

    这里使用的内存是动态开辟的,因此在我们使用完后要及时释放掉内存,否则会造成内存泄漏。

    1. void STDestroy(ST* pst)
    2. {
    3. assert(pst);
    4. free(pst->a);
    5. pst->a = NULL;
    6. pst->top = 0;
    7. pst->capacity = 0;
    8. }

    3. 栈完整源代码

    Stack.h

    1. #include
    2. #include
    3. #include
    4. #include
    5. typedef int STDataType;
    6. typedef struct Stack
    7. {
    8. STDataType* a;
    9. int top; // 标识栈顶位置的
    10. int capacity;
    11. }ST;
    12. void STInit(ST* pst);//初始化
    13. void STDestroy(ST* pst);//销毁
    14. void STPush(ST* pst, STDataType x);//入栈
    15. void STPop(ST* pst);//出栈
    16. STDataType STTop(ST* pst);//读取栈顶元素
    17. bool STEmpty(ST* pst);//判断栈空

    Stack.c

    1. #include"Stack.h"
    2. void STInit(ST* pst)
    3. {
    4. assert(pst);
    5. pst->a = NULL;
    6. pst->capacity = 0;
    7. pst->top = 0;
    8. }
    9. void STDestroy(ST* pst)
    10. {
    11. assert(pst);
    12. free(pst->a);
    13. pst->a = NULL;
    14. pst->top = 0;
    15. pst->capacity = 0;
    16. }
    17. void STPush(ST* pst, STDataType x)
    18. {
    19. assert(pst);
    20. if (pst->top == pst->capacity)
    21. {
    22. int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
    23. STDataType* tmp = calloc(pst->a, sizeof(STDataType) * newcapacity);
    24. if (tmp == NULL)
    25. {
    26. perror("calloc fail");
    27. return;
    28. }
    29. pst->a = tmp;
    30. pst->capacity = newcapacity;
    31. }
    32. pst->a[pst->top] = x;
    33. pst->top++;
    34. }
    35. void STPop(ST* pst)
    36. {
    37. assert(pst);
    38. assert(pst->top > 0);
    39. pst->top--;
    40. }
    41. STDataType STTop(ST* pst)
    42. {
    43. assert(pst);
    44. assert(pst->top > 0);
    45. return pst->a[pst->top - 1];
    46. }
    47. bool STEmpty(ST* pst)
    48. {
    49. assert(pst);
    50. return pst->top == 0;
    51. }

    本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。你们的支持就是博主最大的动力。

  • 相关阅读:
    Python学习第3天:变量与数据类型
    拉链表的展开算法
    SpringCloud源码探析(十)-Web消息推送
    使用 Redis 作为缓存的 Spring Boot 应用
    Java新特性与性能调优
    深度学习 | Transformer 基本原理
    vue-router4 |name的作用|query传参|parmas传参|动态路由参数|命名视图|别名alias|前置路由守卫|路由过渡效果|滚动行为
    python简单实现经典的图像匹配算法SIFT
    html(抽奖设计)
    Android14之input高级调试技巧(一百八十八)
  • 原文地址:https://blog.csdn.net/m0_68662723/article/details/134445188