• 顺序栈(数组模拟)


    栈是一种比较常用的数据结果,其特性是先进后出,常用于某些递归问题非递归求解,单调栈等,顺序栈实际上就是数组模拟栈。

    前置知识:

            realloc函数

    1. //realloc()函数适用于对地址内存的二次申请
    2. //使用方法如下:
    3. int *a;
    4. a=(int*)realloc(a,5*sizeof(int));
    5. //即对a的内存重新申请为5*sizeof(int)

    使用结构体定义一个SqStack数据类型来表示顺序栈

    1. #define StackInitSize 100 //顺序栈的初始大小,当数据超出这个大小我们称其为爆栈
    2. #define StackIncrement 10 //顺序栈存储空间增量
    3. #define SElemType int //自定义栈内数据类型
    4. typedef struct {
    5. SElemType *base; //数组模拟顺序栈
    6. int top; //栈顶指针,即数组末尾下标
    7. int stacksize; //顺序栈的存储空间大小
    8. } SqStack; //定义顺序栈的数据类型

    栈操作:

            栈操作基本分为六个,初始化栈,判断栈空,求栈的长度,入栈,出栈,取栈顶元素。

    初始化栈:

            建立一个空栈,top指针为0,栈的容量stacksize为定义的初始StackInitSize。

    1. void InitStack(SqStack &S) { //初始化栈
    2. //初始时,栈空,top=0
    3. S.base = (SElemType*)malloc(StackInitSize * sizeof(SElemType));
    4. //申请StackInitSize个SElemType类型的内存
    5. if (S.base == NULL) //申请内存失败时,S.base==NULL
    6. return ; //函数停止,不进行以下操作
    7. S.top = 0;
    8. S.stacksize = StackInitSize; //初始化栈的top指针和大小
    9. }
    判断栈空:

            由于是数组模拟栈,我们用到的top下标指针实际上也象征这栈的长度,当长度为0时,栈内无元素,即栈空。

    1. bool StackEmpty(SqStack &S) { //判断栈空
    2. if (S.top == 0)
    3. return true;//1
    4. return false;//0
    5. }
    求栈的长度:

            我们已经分析了top下标指针实际上也象征这栈的长度。

    1. int StackLength(SqStack &S) { //求栈的长度
    2. return S.top;
    3. }
    入栈:

            将元素入栈,top下标指针++偏移一位。

    1. void Push(SqStack &S, SElemType e) { //e入栈S
    2. if (S.top >= S.stacksize) {
    3. //当栈满时,为栈额外申请StackIncrement个SElemtype的内存
    4. S.base = (SElemType*)realloc(S.base, (S.stacksize + StackIncrement) * sizeof(SElemType));
    5. if (S.base == NULL) //申请内存失败时
    6. return ; //停止函数,不再进行下列操作
    7. S.stacksize += StackIncrement; //栈的大小增加
    8. } else { //栈不满时,直接入栈
    9. S.base[S.top++] = e;
    10. /*
    11. 相当于
    12. S.base[S.top]=e;将e存入数组
    13. S.top++; 栈top指针偏移
    14. */
    15. }
    16. }
    出栈:

            栈顶元素一定是最后进栈的,由栈后进先出的性质,出栈元素为栈顶元素

    1. void Pop(SqStack &S, SElemType &e) {
    2. //使用&可以直接改变e的值,这种方法叫做引用
    3. if (S.top == 0) //StackEmpty(S)
    4. return ;
    5. //栈非空时,指针top--,可看作对栈顶出栈
    6. e = S.base[--S.top];
    7. /*--i与i--的区别
    8. S.top--;
    9. e=S.base[S.top];
    10. */
    11. }
    取栈顶元素:
    1. void GetTop(SqStack &S, SElemType &e) {
    2. //得到栈顶元素赋给e
    3. if (S.top == 0)
    4. return;
    5. e = S.base[S.top - 1];
    6. //GetTop()与Pop()之间的差别在于是否有出栈操作
    7. }

    对顺序栈的使用:

    1. #include<bits/stdc++.h>
    2. using namespace std;
    3. #define StackInitSize 100 //顺序栈的初始大小,当数据超出这个大小我们称其为爆栈
    4. #define StackIncrement 10 //顺序栈存储空间增量
    5. #define SElemType int //自定义栈内数据类型
    6. typedef struct {
    7. SElemType *base; //数组模拟顺序栈
    8. int top; //栈顶指针,即数组末尾下标
    9. int stacksize; //顺序栈的存储空间大小
    10. } SqStack; //定义顺序栈的数据类型
    11. void InitStack(SqStack &S) { //初始化栈
    12. //初始时,栈空,top=0
    13. S.base = (SElemType*)malloc(StackInitSize * sizeof(SElemType));
    14. //申请StackInitSize个SElemType类型的内存
    15. if (S.base == NULL) //申请内存失败时,S.base==NULL
    16. return ; //函数停止,不进行以下操作
    17. S.top = 0;
    18. S.stacksize = StackInitSize; //初始化栈的top指针和大小
    19. }
    20. bool StackEmpty(SqStack &S) { //判断栈空
    21. if (S.top == 0)
    22. return true;//1
    23. return false;//0
    24. }
    25. int StackLength(SqStack &S) { //求栈的长度
    26. return S.top;
    27. }
    28. void Push(SqStack &S, SElemType e) { //e入栈S
    29. if (S.top >= S.stacksize) {
    30. //当栈满时,为栈额外申请StackIncrement个SElemtype的内存
    31. S.base = (SElemType*)realloc(S.base, (S.stacksize + StackIncrement) * sizeof(SElemType));
    32. if (S.base == NULL) //申请内存失败时
    33. return ; //停止函数,不再进行下列操作
    34. S.stacksize += StackIncrement; //栈的大小增加
    35. } else { //栈不满时,直接入栈
    36. S.base[S.top++] = e;
    37. /*
    38. 相当于
    39. S.base[S.top]=e;将e存入数组
    40. S.top++; 栈top指针偏移
    41. */
    42. }
    43. }
    44. void Pop(SqStack &S, SElemType &e) {
    45. //使用&可以直接改变e的值,这种方法叫做引用
    46. if (S.top == 0) //StackEmpty(S)
    47. return ;
    48. //栈非空时,指针top--,可看作对栈顶出栈
    49. e = S.base[--S.top];
    50. /*--i与i--的区别
    51. S.top--;
    52. e=S.base[S.top];
    53. */
    54. }
    55. void GetTop(SqStack &S, SElemType &e) {
    56. //得到栈顶元素赋给e
    57. if (S.top == 0)
    58. return;
    59. e = S.base[S.top - 1];
    60. //GetTop()与Pop()之间的差别在于是否有出栈操作
    61. }
    62. int main() {
    63. SqStack st;
    64. InitStack(st);
    65. if (StackEmpty(st)) {
    66. cout << "初始时栈空\n";
    67. }
    68. Push(st, 1); //1入栈
    69. Push(st, 2); //2入栈
    70. Push(st, 3); //3入栈
    71. cout << "此时栈的长度:" << StackLength(st) << "\n";
    72. SElemType tmp;
    73. GetTop(st, tmp); //获取栈顶元素
    74. cout << "栈顶元素为:" << tmp << "\n";
    75. //清栈操作
    76. while (!StackEmpty(st)) { //只要栈不空
    77. Pop(st, tmp); //就执行一次出栈操作
    78. cout << tmp << "出栈\n";
    79. }
    80. }
    运行结果:


    最后提一下共享存储空间的顺序栈,其实质是两个栈和在一起,一个栈顶指针从0开始,一个栈顶指针从n开始(n为栈初始长度),大部分操作与单顺序栈没有太大区别,稍作了解即可。

  • 相关阅读:
    PostgreSQL serial类型
    AI如何帮助Salesforce从业者找工作?
    Vue {{}}里面不同内容
    redis多节点部署实施指引
    linux安装opencv
    接入国家能源平台MQTT应用案例
    Nexus3 安装 及 配置 docker 私有、代理 仓库
    配置鼠标右键edit with notepad
    java毕业设计城市出行行程智能推荐系统Mybatis+系统+数据库+调试部署
    springboot1:项目启动
  • 原文地址:https://blog.csdn.net/qq_74910785/article/details/134026736