当前位置: 首页 > news >正文

数据结构之栈

栈模型

栈有时又叫做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.}

 

 

转载于:https://www.cnblogs.com/Tan-sir/p/7724485.html

相关文章:

  • 课后作业:字串加密
  • 还没升级 iOS11?这个高危漏洞威胁近9成 iPhone 用户!
  • e租宝雇佣黑客攻击网贷之家 帮凶被判二年六个月
  • java.security.AccessControlException: access denied (java.lang.RuntimePermission getClassLoader)
  • 云计算大数据(Hadoop)开发工程师项目实战视频教程(九部分)
  • MySQL设置UTF8字符
  • Web大前端环境搭建
  • Java并发学习之ReentrantLock的工作原理及使用姿势
  • Jedis cluster集群初始化源码剖析
  • Locust no-web 模式与参数详解
  • 我所理解的Remoting (2) :远程对象的生命周期管理[下篇]
  • windows 10、8.1、7 用户自动登陆,避免输入密码登陆的注册表项:
  • 北京航空航天大学王田苗教授:人工智能与机器人前沿科技发展与投资布局
  • YYHS-猜数字(并查集/线段树维护)
  • Linux链接文件
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • CentOS从零开始部署Nodejs项目
  • Gradle 5.0 正式版发布
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Promise面试题,控制异步流程
  • Spring Cloud Feign的两种使用姿势
  • vuex 笔记整理
  • 深度解析利用ES6进行Promise封装总结
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 听说你叫Java(二)–Servlet请求
  • 微信小程序填坑清单
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 一份游戏开发学习路线
  • 最近的计划
  • AI算硅基生命吗,为什么?
  • linux 淘宝开源监控工具tsar
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • #{} 和 ${}区别
  • #宝哥教你#查看jquery绑定的事件函数
  • #在 README.md 中生成项目目录结构
  • (11)MSP430F5529 定时器B
  • (2)(2.10) LTM telemetry
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)重识new
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .axf 转化 .bin文件 的方法
  • .CSS-hover 的解释
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .net core开源商城系统源码,支持可视化布局小程序
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .NET 命令行参数包含应用程序路径吗?