• 带你深入理解“栈”(c语言 c++和stl Stack三个版本的模拟实现)


    目录

    一.栈的概念及结构

    二.栈的实现(c语言版)

    2.1静态增长的栈

    2.2动态增长的栈

    2.3动态栈的模拟实现

       1.栈的初始化

      2.入栈

     3.出栈

    4.获取栈顶元素

    5.获取栈中有效数据个数

    6.检查栈是否为空

    7.栈的销毁

    三.C++ 版本模拟实现栈

     1.C++版本的源代码

    四.c语言版本的源代码

      4.1  头文件.h源码

      4.2 功能实现的.c文件

    4.3测试代码test.c文件


    一.栈的概念及结构

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

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

    二.栈的实现(c语言版)

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

    2.1静态增长的栈

    下面是定长的静态栈的结构,栈的内存空间是固定的,当我们栈中的数据很少时,可能会浪费空间,而数据量很大的时候,栈有可能占不下大量的数据,所以,在实际中一般不实用。

    1. typedef int STDataType;
    2. #define N 10
    3. typedef struct Stack
    4. {
    5. STDataType _a[N];
    6. int _top; // 栈顶
    7. }Stack;

    2.2动态增长的栈

    下面是动态增长的栈,初始化的时候可以先给_a一个固定的小值,如何根据用户输入的数据自我进行扩容

    1. typedef int STDataType;
    2. typedef struct Stack
    3. {
    4. STDataType* _a;
    5. int _top; // 栈顶
    6. int _capacity; // 容量
    7. }Stack;

    2.3动态栈的模拟实现

       1.栈的初始化

      在这里我对“栈”的容量给予5,然后用malloc去堆上创建5个int字节大小的空间付给我们的数组,因为malloc有可能申请失败,所以我们用if去进行判断。

      top栈顶初始化为0,代表没有数据。

    1. void StackInit(Stack* ps)
    2. {
    3.     ps->capacity = 5;
    4.     ps->a = (Stack*)malloc(ps->capacity * sizeof(STDataType));
    5.     if (ps->a == NULL)
    6.     {
    7.         perror("malloc");
    8.         exit(-1);
    9.     }
    10.     ps->top = 0;
    11. }

      2.入栈

    入栈,栈里面插入数据,相当于数组进行尾插

    首先,进行判断,top栈顶等于capacity容量的时候,代表我们栈里的内存满了,这里我们需要扩容,用realloc对数组进行扩容,现在我进行的二倍扩容

    判断完成后 进行插入数据,在数组栈顶插入传入的数据 data

    1. void StackPush(Stack* ps, STDataType data)
    2. {
    3. //扩容
    4. if (ps->top == ps->capacity)
    5. {
    6. Stack * da = (Stack*)realloc( ps->a ,ps->capacity * 2 * sizeof(STDataType));
    7. if (da == NULL)
    8. {
    9. perror("realloc");
    10. exit(-1);
    11. }
    12. else
    13. {
    14. ps->a = da;
    15. }
    16. ps->capacity *= 2;
    17. }
    18. ps->a[ps->top] = data;
    19. ps->top++;
    20. }

     3.出栈

    出栈,直接栈顶元素减一就好了,以后插入的数据会直接替换原先的数据,而top--后自己也访问不到top以后的数据

    1. void StackPop(Stack* ps)
    2. {
    3. ps->top--;
    4. }

    4.获取栈顶元素

    获取栈顶元素,因为数组下标是从0开始的,所以返回的是栈顶元素-1;

    1. STDataType StackTop(Stack* ps)
    2. {
    3. return ps->a[ps->top-1];
    4. }

    5.获取栈中有效数据个数

    有效的数据个数就是 栈顶,直接返回栈顶就好了

    1. int StackSize(Stack* ps)
    2. {
    3. return ps->top;
    4. }

    6.检查栈是否为空

    c语言并不支持bool,需要我们引用头文件#include

    判断栈顶是否为0,来判断栈里是否有数据

    有返回true

    无返回false

    1. bool StackEmpty(Stack* ps)
    2. {
    3. if (ps->top == 0)
    4. return true;
    5. else
    6. return false;
    7. }

    7.栈的销毁

    栈的销毁,对容量和栈顶进行请0,然后用free函数释放我们使用malloc/realloc在堆上开辟的空间

    1. void StackDestroy(Stack* ps)
    2. {
    3. ps->capacity = 0;
    4. ps->top = 0;
    5. free(ps->a);
    6. ps->a = NULL;
    7. }

    以上就是c语言版本的栈的模拟实现

    三.C++ 版本模拟实现栈

    考虑到学校有好多老师上课,虽然说得是用c语言实现,却用cpp进行操作,现在给大家更新cpp版本的栈的模拟实现,cpp版本的扩容使用的new,函数参数使用的&,可能有同学对指针使用不太熟悉,所以我们同意用&(引用)来实现,方便大家的理解,就不再详细的进行说明了,思路跟c语言实现的一样,只是c和cpp的语言差距有所不同。

     1.C++版本的源代码

    1. #include<iostream>
    2. using namespace std;
    3. // 支持动态增长的栈
    4. typedef int STDataType;
    5. typedef struct Stack1
    6. {
    7. STDataType* a;
    8. int top; // 栈顶
    9. int capacity; // 容量
    10. }Stack;
    11. // 初始化栈
    12. void StackInit(Stack& ps)
    13. {
    14. ps.capacity = 5;
    15. ps.a = new STDataType[ps.capacity * sizeof(STDataType)];
    16. ps.top = 0;
    17. }
    18. // 入栈
    19. void StackPush(Stack& ps, STDataType data)
    20. {
    21. //扩容
    22. if (ps.top == ps.capacity)
    23. {
    24. STDataType* da = new STDataType[ps.capacity * 2 * sizeof(STDataType)];
    25. ps.a = da;
    26. ps.capacity *= 2;
    27. }
    28. ps.a[ps.top] = data;
    29. ps.top++;
    30. }
    31. // 出栈
    32. void StackPop(Stack& ps)
    33. {
    34. ps.top--;
    35. }
    36. // 获取栈顶元素
    37. STDataType StackTop(const Stack& ps)
    38. {
    39. return ps.a[ps.top - 1];
    40. }
    41. // 获取栈中有效元素个数
    42. int StackSize(const Stack& ps)
    43. {
    44. return ps.top;
    45. }
    46. // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
    47. bool StackEmpty( const Stack& ps)
    48. {
    49. if (ps.top == 0)
    50. return true;
    51. else
    52. return false;
    53. }
    54. // 销毁栈
    55. void StackDestroy(Stack& ps)
    56. {
    57. ps.capacity = 0;
    58. ps.top = 0;
    59. delete ps.a;
    60. ps.a = NULL;
    61. }
    62. int main()
    63. {
    64. Stack s;
    65. StackInit(s);
    66. StackPush(s, 1);
    67. StackPush(s, 2);
    68. StackPush(s, 3);
    69. StackPush(s, 4);
    70. for (int i = 0;i < 4;i++)
    71. {
    72. cout << StackTop(s) << endl;
    73. StackPop(s);
    74. }
    75. printf("栈中有效元素个数为 %d \n", StackSize(s));
    76. if (StackEmpty(s))
    77. {
    78. printf("为空\n");
    79. }
    80. else
    81. {
    82. printf("不为空\n");
    83. }
    84. StackDestroy(s);
    85. }

    四.c语言版本的源代码

      4.1  头文件.h源码

    1. #include<stdio.h>
    2. #include<stdlib.h>
    3. #include<stdbool.h>
    4. // 支持动态增长的栈
    5. typedef int STDataType;
    6. typedef struct Stack
    7. {
    8. STDataType* a;
    9. int top; // 栈顶
    10. int capacity; // 容量
    11. }Stack;
    12. // 初始化栈
    13. void StackInit(Stack* ps);
    14. // 入栈
    15. void StackPush(Stack* ps, STDataType data);
    16. // 出栈
    17. void StackPop(Stack* ps);
    18. // 获取栈顶元素
    19. STDataType StackTop(Stack* ps);
    20. // 获取栈中有效元素个数
    21. int StackSize(Stack* ps);
    22. // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
    23. bool StackEmpty(Stack* ps);
    24. // 销毁栈
    25. void StackDestroy(Stack* ps);

      4.2 功能实现的.c文件

    1. #include"Stack.h"
    2. // 初始化栈
    3. void StackInit(Stack* ps)
    4. {
    5. assert(ps);
    6. ps->capacity = 5;
    7. ps->a = (Stack*)malloc(ps->capacity * sizeof(STDataType));
    8. if (ps->a == NULL)
    9. {
    10. perror("malloc");
    11. exit(-1);
    12. }
    13. ps->top = 0;
    14. }
    15. // 入栈
    16. void StackPush(Stack* ps, STDataType data)
    17. {
    18. assert(ps);
    19. //扩容
    20. if (ps->top == ps->capacity)
    21. {
    22. Stack * da = (Stack*)realloc( ps->a ,ps->capacity * 2 * sizeof(STDataType));
    23. if (da == NULL)
    24. {
    25. perror("realloc");
    26. exit(-1);
    27. }
    28. else
    29. {
    30. ps->a = da;
    31. }
    32. ps->capacity *= 2;
    33. }
    34. ps->a[ps->top] = data;
    35. ps->top++;
    36. }
    37. // 出栈
    38. void StackPop(Stack* ps)
    39. {
    40. assert(ps);
    41. assert(ps->top > 0);
    42. ps->top--;
    43. }
    44. // 获取栈顶元素
    45. STDataType StackTop(Stack* ps)
    46. {
    47. assert(ps);
    48. return ps->a[ps->top-1];
    49. }
    50. // 获取栈中有效元素个数
    51. int StackSize(Stack* ps)
    52. {
    53. return ps->top;
    54. }
    55. // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
    56. bool StackEmpty(Stack* ps)
    57. {
    58. if (ps->top == 0)
    59. return true;
    60. else
    61. return false;
    62. }
    63. // 销毁栈
    64. void StackDestroy(Stack* ps)
    65. {
    66. assert(ps);
    67. ps->capacity = 0;
    68. ps->top = 0;
    69. free(ps->a);
    70. ps->a = NULL;
    71. }

    4.3测试代码test.c文件

    1. #include"Stack.h"
    2. int main()
    3. {
    4. Stack s;
    5. StackInit(&s);
    6. StackPush(&s, 1);
    7. StackPush(&s, 2);
    8. StackPush(&s, 3);
    9. StackPush(&s, 4);
    10. StackPop(&s);
    11. printf("栈顶元素为%d \n", StackTop(&s));
    12. printf("栈中有效元素个数为 %d \n", StackSize(&s));
    13. if (StackEmpty(&s))
    14. {
    15. printf("为空\n");
    16. }
    17. else
    18. {
    19. printf("不为空\n");
    20. }
    21. StackDestroy(&s);
    22. }

  • 相关阅读:
    软考中级网络工程师全面学习笔记第2版(5万字)+配套视频及课件
    两大Mac内存清理方法,嫌麻烦的就直接使用第二种
    硬盘使用时间如何修改?
    前端element的el-tooltip鼠标经过显示文字,没有文字显示空黑框问题
    Linux各种命令-查询篇
    【数据结构】顺序表实现通讯录
    leetcode 547.省份数量 并查集
    配置vue前端服务器及express服务器端的服务器同时运行——concurrently
    【22年】2022最新阿里Java面经,转疯了
    Zookeeper面试题整理含答案
  • 原文地址:https://blog.csdn.net/weixin_55582891/article/details/134074099