1. 栈的介绍

2. 栈的应用

3. 栈入门

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "errors"
  6. )
  7.  
  8. //使用数组来模拟一个栈的使用
  9. type Stack struct {
  10. MaxTop int // 表示我们栈最大可以存放数个数
  11. Top int // 表示栈顶, 因为栈顶固定,因此我们直接使用Top
  12. arr [5]int // 数组模拟栈
  13. }
  14.  
  15. //入栈
  16. func (this *Stack) Push(val int) (err error) {
  17.  
  18. //先判断栈是否满了
  19. if this.Top == this.MaxTop-1 {
  20. fmt.Println("stack full")
  21. return errors.New("stack full")
  22. }
  23. this.Top++
  24. //放入数据
  25. this.arr[this.Top] = val
  26. return
  27. }
  28.  
  29. //出栈
  30. func (this *Stack) Pop() (val int, err error) {
  31. //判断栈是否空
  32. if this.Top == -1 {
  33. fmt.Println("stack empty!")
  34. return 0, errors.New("stack empty")
  35. }
  36.  
  37. //先取值,再 this.Top--
  38. val = this.arr[this.Top]
  39. this.Top--
  40. return val, nil
  41.  
  42. }
  43.  
  44. //遍历栈,注意需要从栈顶开始遍历
  45. func (this *Stack) List() {
  46. //先判断栈是否为空
  47. if this.Top == -1 {
  48. fmt.Println("stack empty")
  49. return
  50. }
  51. fmt.Println("栈的情况如下:")
  52. for i := this.Top; i >= 0; i-- {
  53. fmt.Printf("arr[%d]=%d\n", i, this.arr[i])
  54. }
  55.  
  56. }
  57.  
  58. func main() {
  59.  
  60. stack := &Stack{
  61. MaxTop: 5, // 表示最多存放5个数到栈中
  62. Top: -1, // 当栈顶为-1,表示栈为空
  63. }
  64.  
  65. //入栈
  66. stack.Push(1)
  67. stack.Push(2)
  68. stack.Push(3)
  69. stack.Push(4)
  70. stack.Push(5)
  71.  
  72. //显示
  73. stack.List()
  74. val, _ := stack.Pop()
  75. fmt.Println("出栈val=", val) // 5
  76. //显示
  77. stack.List() //
  78.  
  79. fmt.Println()
  80. val, _ = stack.Pop()
  81. val, _ = stack.Pop()
  82. val, _ = stack.Pop()
  83. val, _ = stack.Pop()
  84. val, _ = stack.Pop() // 出错
  85. fmt.Println("出栈val=", val) // 5
  86. //显示
  87. stack.List() //
  88. }

4. 栈的计算表达式

  1. package main
  2. import (
  3. "fmt"
  4. "errors"
  5. "strconv"
  6. )
  7.  
  8. //使用数组来模拟一个栈的使用
  9. type Stack struct {
  10. MaxTop int // 表示我们栈最大可以存放数个数
  11. Top int // 表示栈顶, 因为栈顶固定,因此我们直接使用Top
  12. arr [20]int // 数组模拟栈
  13. }
  14. //入栈
  15. func (this *Stack) Push(val int) (err error) {
  16.  
  17. //先判断栈是否满了
  18. if this.Top == this.MaxTop - 1 {
  19. fmt.Println("stack full")
  20. return errors.New("stack full")
  21. }
  22. this.Top++
  23. //放入数据
  24. this.arr[this.Top] = val
  25. return
  26. }
  27.  
  28. //出栈
  29. func (this *Stack) Pop() (val int, err error) {
  30. //判断栈是否空
  31. if this.Top == -1 {
  32. fmt.Println("stack empty!")
  33. return 0, errors.New("stack empty")
  34. }
  35.  
  36. //先取值,再 this.Top--
  37. val = this.arr[this.Top]
  38. this.Top--
  39. return val, nil
  40.  
  41. }
  42. //遍历栈,注意需要从栈顶开始遍历
  43. func (this *Stack) List() {
  44. //先判断栈是否为空
  45. if this.Top == -1 {
  46. fmt.Println("stack empty")
  47. return
  48. }
  49. fmt.Println("栈的情况如下:")
  50. for i := this.Top; i >= 0; i-- {
  51. fmt.Printf("arr[%d]=%d\n", i, this.arr[i])
  52. }
  53.  
  54. }
  55. //判断一个字符是不是一个运算符[+, - , * , /]
  56. func (this *Stack) IsOper(val int) bool {
  57.  
  58. if val == 42 || val == 43 || val == 45 || val == 47 {
  59. return true
  60. } else {
  61. return false
  62. }
  63. }
  64.  
  65. //运算的方法
  66. func (this *Stack) Cal(num1 int, num2 int, oper int) int{
  67. res := 0
  68. switch oper {
  69. case 42 :
  70. res = num2 * num1
  71. case 43 :
  72. res = num2 + num1
  73. case 45 :
  74. res = num2 - num1
  75. case 47 :
  76. res = num2 / num1
  77. default :
  78. fmt.Println("运算符错误.")
  79. }
  80. return res
  81. }
  82.  
  83. //编写一个方法,返回某个运算符的优先级[程序员定义]
  84. //[* / => 1 + - => 0]
  85. func (this *Stack) Priority(oper int) int {
  86. res := 0
  87. if oper == 42 || oper == 47 {
  88. res = 1
  89. } else if oper == 43 || oper == 45 {
  90. res = 0
  91. }
  92. return res
  93. }
  94.  
  95. func main() {
  96.  
  97. //数栈
  98. numStack := &Stack{
  99. MaxTop : 20,
  100. Top : -1,
  101. }
  102. //符号栈
  103. operStack := &Stack{
  104. MaxTop : 20,
  105. Top : -1,
  106. }
  107.  
  108. exp := "30+30*6-4-6"
  109. //定义一个index ,帮助扫描exp
  110. index := 0
  111. //为了配合运算,我们定义需要的变量
  112. num1 := 0
  113. num2 := 0
  114. oper := 0
  115. result := 0
  116. keepNum := ""
  117.  
  118. for {
  119. //这里我们需要增加一个逻辑,
  120. //处理多位数的问题
  121. ch := exp[index:index+1] // 字符串.
  122. //ch ==>"+" ===> 43
  123. temp := int([]byte(ch)[0]) // 就是字符对应的ASCiI码
  124. if operStack.IsOper(temp) { // 说明是符号
  125.  
  126. //如果operStack 是一个空栈, 直接入栈
  127. if operStack.Top == -1 { //空栈
  128. operStack.Push(temp)
  129. }else {
  130. //如果发现opertStack栈顶的运算符的优先级大于等于当前准备入栈的运算符的优先级
  131. //,就从符号栈pop出,并从数栈也pop 两个数,进行运算,运算后的结果再重新入栈
  132. //到数栈, 当前符号再入符号栈
  133. if operStack.Priority(operStack.arr[operStack.Top]) >=
  134. operStack.Priority(temp) {
  135. num1, _ = numStack.Pop()
  136. num2, _ = numStack.Pop()
  137. oper, _ = operStack.Pop()
  138. result = operStack.Cal(num1,num2, oper)
  139. //将计算结果重新入数栈
  140. numStack.Push(result)
  141. //当前的符号压入符号栈
  142. operStack.Push(temp)
  143.  
  144. }else {
  145. operStack.Push(temp)
  146. }
  147.  
  148. }
  149.  
  150. } else { //说明是数
  151.  
  152. //处理多位数的思路
  153. //1.定义一个变量 keepNum string, 做拼接
  154. keepNum += ch
  155. //2.每次要向index的后面字符测试一下,看看是不是运算符,然后处理
  156. //如果已经到表达最后,直接将 keepNum
  157. if index == len(exp) - 1 {
  158. val, _ := strconv.ParseInt(keepNum, 10, 64)
  159. numStack.Push(int(val))
  160. } else {
  161. //向index 后面测试看看是不是运算符 [index]
  162. if operStack.IsOper(int([]byte(exp[index+1:index+2])[0])) {
  163. val, _ := strconv.ParseInt(keepNum, 10, 64)
  164. numStack.Push(int(val))
  165. keepNum = ""
  166. }
  167. }
  168. }
  169.  
  170. //继续扫描
  171. //先判断index是否已经扫描到计算表达式的最后
  172. if index + 1 == len(exp) {
  173. break
  174. }
  175. index++
  176.  
  177. }
  178.  
  179. //如果扫描表达式 完毕,依次从符号栈取出符号,然后从数栈取出两个数,
  180. //运算后的结果,入数栈,直到符号栈为空
  181. for {
  182. if operStack.Top == -1 {
  183. break //退出条件
  184. }
  185. num1, _ = numStack.Pop()
  186. num2, _ = numStack.Pop()
  187. oper, _ = operStack.Pop()
  188. result = operStack.Cal(num1,num2, oper)
  189. //将计算结果重新入数栈
  190. numStack.Push(result)
  191.  
  192. }
  193.  
  194. //如果我们的算法没有问题,表达式也是正确的,则结果就是numStack最后数
  195. res, _ := numStack.Pop()
  196. fmt.Printf("表达式%s = %v", exp, res)
  197. }

  

Go_栈的更多相关文章

  1. 通往全栈工程师的捷径 —— react

    腾讯Bugly特约作者: 左明 首先,我们来看看 React 在世界范围的热度趋势,下图是关键词“房价”和 “React” 在 Google Trends 上的搜索量对比,蓝色的是 React,红色的 ...

  2. Java 堆内存与栈内存异同(Java Heap Memory vs Stack Memory Difference)

    --reference Java Heap Memory vs Stack Memory Difference 在数据结构中,堆和栈可以说是两种最基础的数据结构,而Java中的栈内存空间和堆内存空间有 ...

  3. duang~免费的学习视频来啦:学霸君之全栈测试

    学霸君向童鞋们推荐一款 同名学霸学习 视频教程 重点是完全免费收看学习噢!!! 今天 学霸君推荐腾讯课堂的学霸君之全栈测试 复制下方链接至腾讯课堂中报名学习 https://ke.qq.com/cou ...

  4. [数据结构]——链表(list)、队列(queue)和栈(stack)

    在前面几篇博文中曾经提到链表(list).队列(queue)和(stack),为了更加系统化,这里统一介绍着三种数据结构及相应实现. 1)链表 首先回想一下基本的数据类型,当需要存储多个相同类型的数据 ...

  5. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  6. BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]

    4453: cys就是要拿英魂! Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 90  Solved: 46[Submit][Status][Discu ...

  7. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...

  8. .NET全栈开发工程师学习路径

    PS:最近一直反复地看博客园以前发布的一条.NET全栈开发工程师的招聘启事,觉得这是我看过最有创意也最朴实的一个招聘启事,更为重要的是它更像是一个技术提纲,能够指引我们的学习和提升,现在转载过来与各位 ...

  9. Nodejs之MEAN栈开发(八)---- 用户认证与会话管理详解

    用户认证与会话管理基本上是每个网站必备的一个功能.在Asp.net下做的比较多,大体的思路都是先根据用户提供的用户名和密码到数据库找到用户信息,然后校验,校验成功之后记住用户的姓名和相关信息,这个信息 ...

随机推荐

  1. Python中需要注意的一些小坑

    Python小知识 # a = a + b /a += b 有时是不一样的​ a=[1,2,3] b = a a = a + [4,5,6] ​ # a=[1,2,3] # b = a # a += ...

  2. Wannafly Camp 2020 Day 3A 黑色气球

    #include <bits/stdc++.h> using namespace std; int a[1005][1005],n,x[1005]; int main() { scanf( ...

  3. PP: Tripoles: A new class of relationships in time series data

    Problem: ?? mining relationships in time series data; A new class of relationships in time series da ...

  4. laravel的Validation检索验证错误消息

    基本用法 处理错误消息 错误消息和视图 可用的验证规则 有条件地添加规则 自定义错误消息 自定义验证规则 基本用法 Laravel提供了一个简单.方便的工具,用于验证数据并通过validation类检 ...

  5. JFinalSwagger插件

    个人博客 地址:http://www.wenhaofan.com/article/20190304101839 jfinal使用swagger的极简插件 码云地址:https://gitee.com/ ...

  6. Vue 实例挂载的实现(六)

    Vue 中我们是通过 $mount 实例方法去挂载 vm 的,$mount 方法在多个文件中都有定义,如 src/platform/web/entry-runtime-with-compiler.js ...

  7. 自定义Ribbon客户端策略

    说明   为了实现Ribbon细粒度的划分,让调用不同的微服务时采用不同的客户端负载均衡策略, 通常情况下我们会自定义配置策略.   本文以内容中心(content-center)调用户中心微服务(u ...

  8. C语言sprintf函数的深入理解

    由于sprintf跟printf在用法上几乎一样,只是打印的目的地不同而已,前者打印到字符串中,后者则直接在命令行上输出.这也导致sprintf比printf有用得多.所以本文着重介绍sprintf, ...

  9. python之路模块

    time模块 print time.time() print time.mktime(time.localtime()) print time.gmtime() #可加时间戳参数 print time ...

  10. OpenGL 编程指南 (3.1)

    1.OpenGL使用的是RGB颜色空间,例如三个颜色分量各占8位,那么就说这个颜色值色深24,能够表示2^24中颜色. 2.多重采样是基于采样的抗锯齿技术,有OGAA(ordered grid ant ...