深圳幻海软件技术有限公司 欢迎您!

【数据结构】栈的实现

2023-04-19

你内心肯定有有着某种火焰,能把你和其他人区别开来。          --库切目录 🚗一.栈的概念及结构🚒二.栈的基本操作 🍗1.栈的初始化🥩2.入栈🍊3.栈顶的元素🍒

你内心肯定有有着某种火焰,能把你和其他人区别开来。                   --库切

目录 

🚗一.栈的概念及结构

🚒二.栈的基本操作 

🍗1.栈的初始化

🥩2.入栈

🍊3.栈顶的元素

🍒4.出栈

🍓5.判断栈是否为空

🍌6.栈中的元素个数

​🌶️7.销毁栈

🚙三.栈的全部代码

🍍1.Stack.h:

🥔2.Stack.c:

🍎3.test.c:


🚗一.栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除操作,进行数据的插入和删除操作的一端称为栈顶。另一端称为栈底。栈中数据元素遵循后进先出LIFO(last in first out)。

栈最基本的两个操作就是压栈和出栈。
1.压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
2.出栈:栈的删除操作叫做出栈,出数据也在栈顶。 
通俗的理解其实就是我们之前学习的尾插和尾删,尾插对应的就是压栈,尾删对应的就是出栈。
但是对于尾插,尾删,我们学习了三种结构:顺序表(数组),单链表,双链表。所以这里我们选用哪一种结构来实现栈呢?

对于单链表尾插,尾删,我们每次都需要遍历整个数组,来找到尾,再进行操作,时间复杂度是O(N),所以我们不会使用单链表来实现栈,我们可以选择顺序表(数组)或者双链表来实现。
这里我们选择的是顺序表(数组)。

和之前一样,我们使用结构体来实现:

  1. typedef int STDataType;
  2. typedef struct Stack
  3. {
  4. STDataType* a;//动态数组
  5. STDataType top;//栈顶
  6. int Capacity;//容量
  7. }ST;

🚒二.栈的基本操作 

🍗1.栈的初始化

对于栈的初始化,我们可以先使用malloc动态的给数组开辟几个空间,容量也栈初始化几个。

  1. //初始化栈
  2. void StackInit(ST* ps)
  3. {
  4. assert(ps);
  5. ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);//动态的开辟空间
  6. if (ps->a == NULL)
  7. {
  8. perror("malloc\n");
  9. return;
  10. }
  11. ps->top = 0;
  12. ps->Capacity = 4;//初始化容量为4
  13. }

🥩2.入栈

入栈也就是尾插,这是我们之前学过的,这是非常简单的。但是还是有个小细节要注意,在入栈之前,我们需要判断一下,栈内的容量是否满了,满了就要增容。

  1. // 入栈
  2. void StackPush(ST* ps,STDataType x)
  3. {
  4. assert(ps);
  5. //判断是否满了
  6. if (ps->top == ps->Capacity)
  7. {
  8. STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->Capacity * 2);
  9. if (temp==NULL)
  10. {
  11. perror("realloc\n");
  12. return;
  13. }
  14. else
  15. {
  16. ps->Capacity *= 2;//每次增容尾上一次的二倍
  17. ps->a = temp;
  18. }
  19. }
  20. else
  21. {
  22. ps->a[ps->top] = x;
  23. ps->top++;//栈内入一个数据,top就要往上面走一步
  24. }
  25. }

🍊3.栈顶的元素

我们要打印栈顶的元素要怎么打印呢?当入栈已经结束了之后,我们先打印第一个栈顶的元素,然后再出栈一个,继续打印栈顶的元素,以此类推,直到栈为空。

  1. STDataType StackTop(ST* ps)
  2. {
  3. assert(ps);
  4. assert(ps->top > 0);//这里要断言一下,如果栈为空,就不能打印了
  5. return ps->a[ps->top - 1];
  6. }

🍒4.出栈

出栈也就是我们所说的尾删,数组的尾删只需要把top的位置往前挪一位就行了。

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

🍓5.判断栈是否为空

为什么要判断栈为空呢?因为当我们进行出栈的时候,栈内的元素为依次减小,如果减小到0,就不能继续出栈了。

  1. //判断栈是否为空
  2. bool StackEmpty(ST* ps)//这里我们使用bool来判断
  3. {
  4. assert(ps);
  5. return ps->top == 0;//当ps->top为0的时候,式子成立,即返回真。反之,亦然。
  6. }

我们就先往栈入 1  2  3  4四个数字,再依次出栈出来打印出来看看。

  1. int main()
  2. {
  3. ST st;
  4. StackInit(&st);
  5. StackPush(&st, 1);
  6. StackPush(&st, 2);
  7. StackPush(&st, 3);
  8. StackPush(&st, 4);
  9. while (!StackEmpty(&st))
  10. {
  11. printf("%d ", StackTop(&st));
  12. StackPop(&st);
  13. }
  14. printf("\n");
  15. return 0;
  16. }


很明显这很符合栈的先入后出的特点。

🍌6.栈中的元素个数

我们入了几个元素,top就是机,直接把top打印出来就是栈元素的个数了。

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



🌶️7.销毁栈

当我们退出程序的时候,把栈给销毁一下。

  1. //销毁栈
  2. void StackDestory(ST* ps)
  3. {
  4. free(ps->a);
  5. ps->a = NULL;
  6. ps->Capacity = 0;
  7. ps->top = 0;
  8. }

🚙三.栈的全部代码

🍍1.Stack.h:

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. #include<stdbool.h>
  6. typedef int STDataType;
  7. typedef struct Stack
  8. {
  9. STDataType* a;//动态数组
  10. STDataType top;//栈顶
  11. int Capacity;//容量
  12. }ST;
  13. //初始化栈
  14. void StackInit(ST* ps);
  15. //入栈
  16. void StackPush(ST* ps, STDataType x);
  17. //出栈
  18. void StackPop(ST* ps);
  19. //栈元素的个数
  20. int StackSize(ST* ps);
  21. //判断栈是否为空
  22. bool StackEmpty(ST* ps);
  23. //栈顶的元素是多少
  24. STDataType StackTop(ST* ps);
  25. //销毁栈
  26. void StackDestory(ST* ps);

🥔2.Stack.c:
 

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include"Stack.h"
  3. //初始化栈
  4. void StackInit(ST* ps)
  5. {
  6. assert(ps);
  7. ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
  8. if (ps->a == NULL)
  9. {
  10. perror("malloc\n");
  11. return;
  12. }
  13. ps->top = 0;
  14. ps->Capacity = 4;
  15. }
  16. // 入栈
  17. void StackPush(ST* ps,STDataType x)
  18. {
  19. assert(ps);
  20. //判断是否满了
  21. if (ps->top == ps->Capacity)
  22. {
  23. STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->Capacity * 2);
  24. if (temp==NULL)
  25. {
  26. perror("realloc\n");
  27. return;
  28. }
  29. else
  30. {
  31. ps->Capacity *= 2;
  32. ps->a = temp;
  33. }
  34. }
  35. else
  36. {
  37. ps->a[ps->top] = x;
  38. ps->top++;
  39. }
  40. }
  41. //出栈
  42. void StackPop(ST* ps)
  43. {
  44. assert(ps);
  45. assert(ps->top > 0);
  46. ps->top--;
  47. }
  48. //栈元素的个数
  49. int StackSize(ST* ps)
  50. {
  51. assert(ps);
  52. return ps->top;
  53. }
  54. //判断栈是否为空
  55. bool StackEmpty(ST* ps)
  56. {
  57. assert(ps);
  58. return ps->top == 0;
  59. }
  60. //栈顶的元素是多少
  61. STDataType StackTop(ST* ps)
  62. {
  63. assert(ps);
  64. assert(ps->top > 0);
  65. return ps->a[ps->top - 1];
  66. }
  67. //销毁栈
  68. void StackDestory(ST* ps)
  69. {
  70. free(ps->a);
  71. ps->a = NULL;
  72. ps->Capacity = 0;
  73. ps->top = 0;
  74. }
  75. //打印函数
  76. void StackPrint(ST* ps)
  77. {
  78. assert(ps);
  79. int i = 0;
  80. while (i < ps->top)
  81. {
  82. printf("%d", ps->a[i]);
  83. i++;
  84. }
  85. }

🍎3.test.c:

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include"Stack.h"
  3. ST st;
  4. void Stacktest1()
  5. {
  6. StackInit(&st);
  7. StackPush(&st, 1);
  8. StackPush(&st, 2);
  9. StackPush(&st, 3);
  10. StackPush(&st, 4);
  11. while (!StackEmpty(&st))
  12. {
  13. printf("%d ", StackTop(&st));
  14. StackPop(&st);
  15. }
  16. printf("\n");
  17. }
  18. void Stacktest2()
  19. {
  20. StackInit(&st);
  21. StackPush(&st, 1);
  22. StackPush(&st, 2);
  23. StackPush(&st, 3);
  24. StackPush(&st, 4);
  25. printf("栈内元素的个数:\n");
  26. printf( "%d\n",StackSize(&st));
  27. }
  28. int main()
  29. {
  30. //Stacktest1();
  31. Stacktest2();
  32. return 0;
  33. }




 

 

 

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览44435 人正在系统学习中