• 数据结构之栈


    栈模型

    栈有时又叫做LIFO(先进后出)。

    一般模型:存在某个元素位于栈顶,而该元素是唯一的可见元素。
    栈可能是计算机科学中数组之后最基本的数据结构

    栈的实现

    栈的链表实现

    1.#include <stdio.h>
    2.#include <stdlib.h>
    3.
    4.struct Node;
    5.typedef struct Node *PtrToNode;
    6.typedef PtrToNode Stack;
    7.
    8.struct Node
    9.{
    10. int Element;
    11. PtrToNode Next;
    12.};
    13.
    14.int IsEmpty(Stack S)
    15.{
    16. return S->Next == NULL;
    17.}
    18.
    19.//压入栈
    20.void Push(int X, Stack S)
    21.{
    22. PtrToNode TmpCell;
    23.
    24. TmpCell = malloc(sizeof(struct Node));
    25. if(TmpCell==NULL)
    26. {
    27. printf("空间不足");
    28. }
    29. else
    30. {
    31. TmpCell->Element = X;
    32. TmpCell->Next = S->Next;
    33. S->Next = TmpCell;
    34. }
    35.}
    36.
    37.//返回栈顶元素
    38.int Top(Stack S)
    39.{
    40. if (!IsEmpty(S))
    41. return S->Next->Element;
    42. if ("栈空");
    43. return 0;
    44.}
    45.//弹出
    46.void Pop(Stack S)
    47.{
    48. PtrToNode Firstcell;
    49. if (IsEmpty(S))
    50. {
    51. printf("栈空");
    52. }
    53. else
    54. {
    55. Firstcell = S->Next;
    56. S->Next = S->Next->Next;
    57. free(Firstcell);
    58. }
    59.}
    60.
    61.
    62.void MakeEmpty(Stack S)
    63.{
    64. if(S==NULL)
    65. {
    66. printf("栈空");
    67. }
    68. else
    69. {
    70. while(!IsEmpty(S))
    71. {
    72. Pop(S);
    73. }
    74. }
    75.}
    76.//创建一个空栈
    77.Stack CreateStack(void)
    78.{
    79. Stack S;
    80.
    81. S = malloc(sizeof(struct Node));
    82. if (S == NULL)
    83. printf("空间不足");
    84. MakeEmpty(S);
    85. return S;
    86.}
    优点:没有任何地方设计栈大小(空栈除外)
    缺点:对malloc和free调用都是昂贵的。

    栈的数组实现

    每一个栈有一个TopOfStack,对于空栈它是-1。将X压入栈中,TopOfStack加1,置Stack[TopOfStack]=X,Stack代表具体的数组。

    1.#include <stdio.h>
    2.#include <stdlib.h>
    3.
    4.typedef struct StackRecord *Stack;
    5.
    6.#define EmptyTOS (-1)
    7.#define MinStackSize (5)
    8.
    9.struct StackRecord
    10.{
    11. int CapaCity;
    12. int TopOfStack;
    13. int *Array;
    14.};
    15.
    16.//创建一个空栈的例程
    17.void MakeEmpty(Stack S)
    18.{
    19. S->TopOfStack = EmptyTOS;
    20.}
    21.
    22.//栈的创建
    23.Stack CreatStack(int MaxElements)
    24.{
    25. Stack S;
    26. if(MaxElements<MinStackSize)
    27. {
    28. printf("Error");
    29. }
    30. //分配栈数组空间大小
    31. S->Array = malloc(sizeof(int) * MaxElements);
    32. if(S->Array==NULL)
    33. {
    34. printf("Error");
    35. }
    36. S->CapaCity = MaxElements;
    37. MakeEmpty(S);
    38. return S;
    39.}
    40.
    41.
    42.//释放栈的例程
    43.void DisposeStack(Stack S)
    44.{
    45. if(S!=NULL)
    46. {
    47. free(S->Array);
    48. free(S);
    49. }
    50.}
    51.
    52.//检测一个栈是否空栈
    53.int IsEmpty(Stack S)
    54.{
    55. return S->TopOfStack == EmptyTOS;
    56.}
    57.
    58.//进栈
    59.void Push(int X,Stack S)
    60.{
    61. if( S==NULL)
    62. {
    63. printf("Error");
    64. }
    65. else
    66. {
    67. S->Array[++S->TopOfStack] = X;
    68. }
    69.
    70.}
    71.
    72.//栈顶返回元素
    73.int Top(Stack S)
    74.{
    75. if(!IsEmpty(S))
    76. {
    77. return S->Array[S->TopOfStack];
    78. }
    79. else
    80. {
    81. printf("Error");
    82. }
    83. return 0;
    84.}
    85.
    86.//从栈顶弹出元素
    87. void Pop(Stack S)
    88.{
    89. if(!IsEmpty(S))
    90. {
    91. printf("Error");
    92. }
    93. else
    94. {
    95. S->TopOfStack--;
    96. }
    97.}
    98.
    99. //返回并弹出元素
    100.int TopAndPop(Stack S)
    101.{
    102. if(!IsEmpty(S))
    103. {
    104. return S->Array[S->TopOfStack--];
    105. }
    106. else
    107. {
    108. printf("Error");
    109. }
    110. return 0;
    111.}

    缺点:需要提前声明一个数组的大小

    栈的应用

    平衡符号

    编译器检查对应的符号,比如([])。
    做一个空栈,读入字符直到文件尾。如果字符式是一个开放符号,则将其推入栈中。如果字符是一个封闭符号,则当栈为空时报错。否则,将栈元素弹出。如果弹出符号不是对应的开放符号,则报错。在文件尾,如果栈非空则报错。

    后缀表达式

    又称逆波兰记法。
    中缀到后缀的转换
    a + b * c + ( d * e + f ) * g => a b c * + d e * f + g * +
    1.char cArray[10];
    2. char cRArray[10];
    3. char a;
    4. Stack S=CreatStack(10);//初始化栈
    5. scanf_s("%c", &cArray[0]);
    6. int i = 0, j = 0;
    7. while(cArray[i]!='e')
    8. {
    9. i++;
    10. scanf_s("%c", &cArray[i]);
    11. }
    12. i = 0;
    13. for(int k=0;k<10;)
    14. {
    15. if(cArray[i]=='*'||cArray[i]=='+')//只做+和*的运算
    16. {
    17. if(cArray[i]=='+'&&GetStack(S)=='*')//当前元素+低于*优先级,将栈中元素都输出
    18. {
    19. for(;S->TopOfStack>-1;)
    20. {
    21. cRArray[k++] = GetStack(S);
    22. BackStack(S);
    23. }
    24. }
    25. else
    26. {
    27. InsertStack(S, cArray[i]);//插入栈
    28. }
    29. }
    30. else
    31. {
    32. cRArray[k++] = cArray[i];//数字输出
    33. }
    34. i++;
    35. }
    36.
    37. for(int l=0;l<10;l++)
    38. {
    39. printf("%c", cRArray[l]);
    40. }
    41. while(S->TopOfStack>=-1 )//输出栈尾剩余元素
    42. {
    43. printf("%c", GetStack(S));
    44. BackStack(S);
    45. }

    函数调用

    当系统调用函数的时候,需要存储重要信息,比如寄存器值,返回地址,他们都以抽象的方式置于一个堆顶部。然后控制转移到一个新函数,该函数自由的用它的一些值代替这些寄存器。这些工作可以一个栈完成。所存储的信息称为活动记录或栈帧。当前环境由栈顶描述。当存在太多同时运行着的函数时,用尽栈空间可能会发生。
    尾递归
    1.void PrintList(List L)
    2.{
    3. if(L!=NULL)
    4. {
    5. PrintElement(L->Element);
    6. PrintList(L->Next);
    7. }
    8.}
    在数据足够大的情况下,上面的函数就可能会用尽栈空间。
    在不用存储每次递归调用值的情况下可以像下面这样避免。
    1.void PrintList(List L)
    2.{
    3. top:
    4. if(L!=NULL)
    5. {
    6. PrintElement(L->Element);
    7. L=L->Next;
    8. goto top;
    9. }
    10.}
     
  • 相关阅读:
    BFS(广搜训练题目)
    练习赛1(补题)
    练习赛1(AC题)
    codeup 1743: 算法3-4:表达式求值
    数学相关(更新ing)
    c语言常用函数(更新ing)
    大牛的博客(学习不止,更新不止)
    51nod 1005 大数加法
    js1-----预览js内容
    css10---转载---定位,浮动
  • 原文地址:https://www.cnblogs.com/Tan-sir/p/7724485.html
Copyright © 2020-2023  润新知