数据结构之线性结构-栈

清疚 2022-10-11 15:57 289阅读 0赞

文章目录

    • 基本定义
    • 基本操作
    • 顺序栈
    • 共享栈
    • 链栈
  • 栈的应用
    • 栈的括号匹配

基本定义

先进后出

==栈(Stack)==是只允许在一端进行插入和删除操作的线性表。

栈顶是允许进行插入、删除操作的那一端。

栈底是固定的,不允许进行插入、删除操作的那一端。

空栈是不含任何元素的栈。

n个不同元素进栈,出栈元素不同排列的个数为 1 n + 1 C n 2 n \frac{1}{n+1}C_{n}^{2n} n+11Cn2n。上述公式称为卡特兰(Catalan) 数,可采用数拿归纳法证明。

基本操作

InitStack(&S):初始化栈。构造-一个空栈S,分配内存空间。

DestroyStack(&L):销毁栈。销毁并释放栈S所占用的内存空间。

StackEmpty(S):栈的判空

Push(&S,x):进栈,若栈S未满,则将x加入使之成为新栈顶。

Pop(&S,&x):出栈,若栈S非空,则弹出栈项元素,并用x返回。

GetTop(&S,&x):读取栈顶元素。若栈非空,返回栈顶元素。

顺序栈

栈项指针: s.top, 初始时设置s.top=-1P;栈项元素: s.data[S. top].
进栈操作:栈不满时,栈顶指针先加1,再送值到栈项元素。
出栈操作:栈非空时,先取栈项元素值,再将栈顶指针减1。
栈空条件: s.top==-1;栈满条件: s. top==MaxSize-1;栈长: s. top+1。
由于顺序栈的入栈操作受数组上界的约束,当对栈的最大使用空间估计不足时,有可能发生
栈上溢,此时应及时向用户报告消息,以便及时处理,避免出错。
注意:栈和队列的判空、判满条件,会因实际给的条件不同而变化,上面提到的方法以及下面的代码实现只是在栈顶指针设定的条件下的相应方法,而其他情况则需具体问题具体分析。

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define ElemType int//数据元素的类型
  4. #define MaxSize 50
  5. //定义顺序栈
  6. typedef struct {
  7. ElemType data[MaxSize];//栈元素
  8. int top;//栈顶指针
  9. }SequenceStack;
  10. //初始化
  11. int InitStack(SequenceStack& S) {
  12. S.top = -1;
  13. return 1;
  14. }
  15. //判空
  16. bool StackEmpty(SequenceStack S) {
  17. if (S.top == -1)//栈空
  18. return true;
  19. else//非空
  20. return false;
  21. }
  22. //进栈,若栈S未满,则将x加入使之成为新栈顶。
  23. int Push(SequenceStack& S, ElemType x) {
  24. if (S.top == MaxSize - 1)//栈满
  25. return 0;
  26. S.data[++S.top] = x;//指针加1并传入元素
  27. return 1;
  28. }
  29. //出栈,若栈S非空,则弹出栈项元素,并用x返回。
  30. int Pop(SequenceStack& S, ElemType& x) {
  31. if (S.top == -1)//栈空
  32. return 0;
  33. x = S.data[S.top--];//传出元素并改变指针
  34. return 1;
  35. }
  36. //读取栈顶元素。若栈非空,返回栈顶元素。
  37. int GetTop(SequenceStack& S) {
  38. ElemType x;
  39. if (S.top == -1)//栈空
  40. return 0;
  41. x = S.data[S.top];//传出元素
  42. return x;
  43. }
  44. int main() {
  45. SequenceStack S;
  46. ElemType x=0;
  47. int i;
  48. InitStack(S);
  49. printf_s("进栈:\n ");
  50. for (i = 0; i < 10; i+=2) {
  51. if (Push(S, i))
  52. printf_s(" %d进栈",i);
  53. else
  54. printf_s(" %d进栈失败", i);
  55. }
  56. printf_s("\n ");
  57. if(StackEmpty(S))
  58. printf_s("栈空\n ");
  59. else
  60. printf_s("非空\n ");
  61. printf_s("出栈:\n ");
  62. printf_s("栈顶元素为:%d\n ", GetTop(S));
  63. for (i = 0; i < 10; i += 2) {
  64. if (Pop(S, x))
  65. printf_s(" %d出栈", x);
  66. else
  67. printf_s(" 出栈失败",x);
  68. }
  69. printf_s("\n ");
  70. system("pause");
  71. return 0;
  72. }

共享栈

两个栈共享同一片空间

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define ElemType int//数据元素的类型
  4. #define MaxSize 50
  5. //定义共享栈
  6. typedef struct {
  7. ElemType data[MaxSize];//栈元素
  8. int top0;//0号栈顶指针
  9. int top1;//1号栈顶指针
  10. }ShowStack;
  11. //初始化
  12. int InitShowStack(ShowStack& S) {
  13. S.top0 = -1;
  14. S.top1 = MaxSize;
  15. return 1;
  16. }
  17. //判满
  18. bool ShowStackFull(ShowStack& S) {
  19. if (S.top0 + 1 == S.top1)//栈满
  20. return true;
  21. else
  22. return false;
  23. }
  24. //共享栈入栈
  25. int ShowStackPush(ShowStack& S,int i, ElemType x) {
  26. //i为栈号,取0或1;x为入栈元素
  27. if (i < 0 || i>1) {
  28. printf_s("栈号错误\n");
  29. return 0;
  30. }
  31. if (S.top0 + 1 == S.top1) {
  32. printf_s("栈满\n");
  33. return 0;
  34. }
  35. switch (i)
  36. {
  37. case 0:S.data[++S.top0] = x; return 1; break;
  38. case 1:S.data[--S.top1] = x; return 1; break;
  39. }
  40. }
  41. //共享栈出栈
  42. int ShowStackPop(ShowStack& S, int i) {
  43. //i为栈号,取0或1
  44. if (i < 0 || i>1) {
  45. printf_s("栈号错误\n");
  46. return 0;
  47. }
  48. switch (i)
  49. {
  50. case 0:
  51. if (S.top0 == -1) {
  52. printf_s("栈空\n");
  53. return 0;
  54. }
  55. else {
  56. printf_s("%d出栈\n",S.data[S.top0]);
  57. S.top0--;
  58. return 0;
  59. }
  60. case 1:
  61. if (S.top1 == MaxSize) {
  62. printf_s("栈空\n");
  63. return 1;
  64. }
  65. else {
  66. printf_s("%d出栈\n",S.data[S.top1]);
  67. S.top1++;
  68. return 1;
  69. }
  70. }
  71. }
  72. int main(){
  73. ShowStack S;
  74. int i;
  75. InitShowStack(S);
  76. printf_s("进栈:\n ");
  77. for (i = 0; i < 10; i += 2) {
  78. if (ShowStackPush(S,0,i))
  79. printf_s(" 0号栈%d进栈", i);
  80. else
  81. printf_s(" 0号栈%d进栈失败", i);
  82. if (ShowStackPush(S, 1, i+1))
  83. printf_s(" 1号栈%d进栈", i+1);
  84. else
  85. printf_s(" 1号栈%d进栈失败", i+1);
  86. }
  87. printf_s("\n ");
  88. if (ShowStackFull(S))
  89. printf_s("栈满\n ");
  90. else
  91. printf_s("未满\n ");
  92. printf_s("0号栈出栈:\n ");
  93. for (i = 0; i < 10; i += 2) {
  94. ShowStackPop(S, 0);
  95. }
  96. printf_s("1号栈出栈:\n ");
  97. for (i = 0; i < 10; i += 2) {
  98. ShowStackPop(S, 1);
  99. }
  100. printf_s("\n ");
  101. system("pause");
  102. return 0;
  103. }

链栈

相对于限制操作的链表

可以参考链表

栈的应用

栈的括号匹配

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define MaxSize 10
  4. typedef struct {
  5. char data[MaxSize];//栈元素
  6. int top;//栈顶指针
  7. }SequenceStack;
  8. //初始化
  9. int InitStack(SequenceStack& S) {
  10. S.top = -1;
  11. return 1;
  12. }
  13. //判空
  14. bool StackEmpty(SequenceStack S) {
  15. if (S.top == -1)//栈空
  16. return true;
  17. else//非空
  18. return false;
  19. }
  20. //进栈,若栈S未满,则将x加入使之成为新栈顶。
  21. int Push(SequenceStack& S, char x) {
  22. if (S.top == MaxSize - 1)//栈满
  23. return 0;
  24. S.data[++S.top] = x;//指针加1并传入元素
  25. return 1;
  26. }
  27. //出栈,若栈S非空,则弹出栈项元素,并用x返回。
  28. int Pop(SequenceStack& S, char& x) {
  29. if (S.top == -1)//栈空
  30. return 0;
  31. x = S.data[S.top--];//传出元素并改变指针
  32. return 1;
  33. }
  34. //括号匹配
  35. bool braacketCheck(char str[], int length) {
  36. SequenceStack S;
  37. InitStack(S); //初始化一个栈
  38. for (int i = 0; i < length; i++) {
  39. if (str[i] == '(' || str[i] == '[' || str[i] == '{') {
  40. Push(S, str[i]); //扫描到左括号, 入栈
  41. }
  42. else {
  43. if (StackEmpty(S)) //扫描到右括号, 且当前栈空
  44. return false; //匹配失败
  45. char topElem;
  46. Pop(S, topElem);
  47. //栈顶元素出栈
  48. if (str[i] == ')' && topElem != '(')
  49. return false;
  50. if (str[i] == ']' && topElem != '[')
  51. return false;
  52. if (str[i] == '}' && topElem != '{')
  53. return false;
  54. }
  55. }
  56. return StackEmpty(S);//检索完所有括号后如果栈空说明匹配成功
  57. }
  58. int main() {
  59. char str[8] = {
  60. '{','[','[','(',')',']',']','}'};
  61. if (braacketCheck(str, 8)) {
  62. printf_s("匹配成功\n");
  63. }
  64. else {
  65. printf_s("匹配失败\n");
  66. }
  67. system("pause");
  68. return 0;
  69. }

发表评论

表情:
评论列表 (有 0 条评论,289人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线性结构 --

    前言 栈和队列是两种重要的线性结构。从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子集,它们是操作受限的线性表,因此,可称为限定性的数