1. 栈的介绍

2. 栈的应用

3. 栈入门

package main

import (
"fmt"
"errors"
) //使用数组来模拟一个栈的使用
type Stack struct {
MaxTop int // 表示我们栈最大可以存放数个数
Top int // 表示栈顶, 因为栈顶固定,因此我们直接使用Top
arr [5]int // 数组模拟栈
} //入栈
func (this *Stack) Push(val int) (err error) { //先判断栈是否满了
if this.Top == this.MaxTop-1 {
fmt.Println("stack full")
return errors.New("stack full")
}
this.Top++
//放入数据
this.arr[this.Top] = val
return
} //出栈
func (this *Stack) Pop() (val int, err error) {
//判断栈是否空
if this.Top == -1 {
fmt.Println("stack empty!")
return 0, errors.New("stack empty")
} //先取值,再 this.Top--
val = this.arr[this.Top]
this.Top--
return val, nil } //遍历栈,注意需要从栈顶开始遍历
func (this *Stack) List() {
//先判断栈是否为空
if this.Top == -1 {
fmt.Println("stack empty")
return
}
fmt.Println("栈的情况如下:")
for i := this.Top; i >= 0; i-- {
fmt.Printf("arr[%d]=%d\n", i, this.arr[i])
} } func main() { stack := &Stack{
MaxTop: 5, // 表示最多存放5个数到栈中
Top: -1, // 当栈顶为-1,表示栈为空
} //入栈
stack.Push(1)
stack.Push(2)
stack.Push(3)
stack.Push(4)
stack.Push(5) //显示
stack.List()
val, _ := stack.Pop()
fmt.Println("出栈val=", val) // 5
//显示
stack.List() // fmt.Println()
val, _ = stack.Pop()
val, _ = stack.Pop()
val, _ = stack.Pop()
val, _ = stack.Pop()
val, _ = stack.Pop() // 出错
fmt.Println("出栈val=", val) // 5
//显示
stack.List() //
}

4. 栈的计算表达式

package main
import (
"fmt"
"errors"
"strconv"
) //使用数组来模拟一个栈的使用
type Stack struct {
MaxTop int // 表示我们栈最大可以存放数个数
Top int // 表示栈顶, 因为栈顶固定,因此我们直接使用Top
arr [20]int // 数组模拟栈
}
//入栈
func (this *Stack) Push(val int) (err error) { //先判断栈是否满了
if this.Top == this.MaxTop - 1 {
fmt.Println("stack full")
return errors.New("stack full")
}
this.Top++
//放入数据
this.arr[this.Top] = val
return
} //出栈
func (this *Stack) Pop() (val int, err error) {
//判断栈是否空
if this.Top == -1 {
fmt.Println("stack empty!")
return 0, errors.New("stack empty")
} //先取值,再 this.Top--
val = this.arr[this.Top]
this.Top--
return val, nil }
//遍历栈,注意需要从栈顶开始遍历
func (this *Stack) List() {
//先判断栈是否为空
if this.Top == -1 {
fmt.Println("stack empty")
return
}
fmt.Println("栈的情况如下:")
for i := this.Top; i >= 0; i-- {
fmt.Printf("arr[%d]=%d\n", i, this.arr[i])
} }
//判断一个字符是不是一个运算符[+, - , * , /]
func (this *Stack) IsOper(val int) bool { if val == 42 || val == 43 || val == 45 || val == 47 {
return true
} else {
return false
}
} //运算的方法
func (this *Stack) Cal(num1 int, num2 int, oper int) int{
res := 0
switch oper {
case 42 :
res = num2 * num1
case 43 :
res = num2 + num1
case 45 :
res = num2 - num1
case 47 :
res = num2 / num1
default :
fmt.Println("运算符错误.")
}
return res
} //编写一个方法,返回某个运算符的优先级[程序员定义]
//[* / => 1 + - => 0]
func (this *Stack) Priority(oper int) int {
res := 0
if oper == 42 || oper == 47 {
res = 1
} else if oper == 43 || oper == 45 {
res = 0
}
return res
} func main() { //数栈
numStack := &Stack{
MaxTop : 20,
Top : -1,
}
//符号栈
operStack := &Stack{
MaxTop : 20,
Top : -1,
} exp := "30+30*6-4-6"
//定义一个index ,帮助扫描exp
index := 0
//为了配合运算,我们定义需要的变量
num1 := 0
num2 := 0
oper := 0
result := 0
keepNum := "" for {
//这里我们需要增加一个逻辑,
//处理多位数的问题
ch := exp[index:index+1] // 字符串.
//ch ==>"+" ===> 43
temp := int([]byte(ch)[0]) // 就是字符对应的ASCiI码
if operStack.IsOper(temp) { // 说明是符号 //如果operStack 是一个空栈, 直接入栈
if operStack.Top == -1 { //空栈
operStack.Push(temp)
}else {
//如果发现opertStack栈顶的运算符的优先级大于等于当前准备入栈的运算符的优先级
//,就从符号栈pop出,并从数栈也pop 两个数,进行运算,运算后的结果再重新入栈
//到数栈, 当前符号再入符号栈
if operStack.Priority(operStack.arr[operStack.Top]) >=
operStack.Priority(temp) {
num1, _ = numStack.Pop()
num2, _ = numStack.Pop()
oper, _ = operStack.Pop()
result = operStack.Cal(num1,num2, oper)
//将计算结果重新入数栈
numStack.Push(result)
//当前的符号压入符号栈
operStack.Push(temp) }else {
operStack.Push(temp)
} } } else { //说明是数 //处理多位数的思路
//1.定义一个变量 keepNum string, 做拼接
keepNum += ch
//2.每次要向index的后面字符测试一下,看看是不是运算符,然后处理
//如果已经到表达最后,直接将 keepNum
if index == len(exp) - 1 {
val, _ := strconv.ParseInt(keepNum, 10, 64)
numStack.Push(int(val))
} else {
//向index 后面测试看看是不是运算符 [index]
if operStack.IsOper(int([]byte(exp[index+1:index+2])[0])) {
val, _ := strconv.ParseInt(keepNum, 10, 64)
numStack.Push(int(val))
keepNum = ""
}
}
} //继续扫描
//先判断index是否已经扫描到计算表达式的最后
if index + 1 == len(exp) {
break
}
index++ } //如果扫描表达式 完毕,依次从符号栈取出符号,然后从数栈取出两个数,
//运算后的结果,入数栈,直到符号栈为空
for {
if operStack.Top == -1 {
break //退出条件
}
num1, _ = numStack.Pop()
num2, _ = numStack.Pop()
oper, _ = operStack.Pop()
result = operStack.Cal(num1,num2, oper)
//将计算结果重新入数栈
numStack.Push(result) } //如果我们的算法没有问题,表达式也是正确的,则结果就是numStack最后数
res, _ := numStack.Pop()
fmt.Printf("表达式%s = %v", exp, res)
}

  

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. 安装postman时遇到“无法定位程序输入点 SetDefaultDllDirectories于动态链接库KERNEL32.dll 上.”的问题

    安装postman时遇到“无法定位程序输入点 SetDefaultDllDirectories于动态链接库KERNEL32.dll 上.”的问题 解决办法: 1.安装系统更新补丁KB2533623,下 ...

  2. AntDesign(React)学习-10 Dva 与后台数据交互

    明天正式在线办公没时间学习了,今天晚上再更新一篇, 代码提交一次:https://github.com/zhaogaojian/jgdemo 1.src下创建services目录 创建文件userSr ...

  3. resize函数

    #include<opencv2/opencv.hpp>#include<opencv2/highgui.hpp> using namespace cv;using names ...

  4. [BJWC2010] 外星联络 - 后缀数组

    [BJWC2010] 外星联络 Description 求一个 \(01\) 串中所有重复出现次数大于 \(1\) 的子串所出现的次数,按照字典序排序输出. Solution 预处理出后缀数组和高度数 ...

  5. js或者jq的string类型或者number类型的相互转换及json对象与字符串的转换

    1.将值乘以1,将string类型转为number类型 //算合计价值function summoney(money) { var zijin = $("#main_xm_dam09&quo ...

  6. c数据结构 -- 栈与队列

    栈和队列 ·栈和队列是两种常用的.重要的数据结构 ·栈和队列是限定插入和删除只能在表的“端点”进行的线性表 栈 只能在队尾插入,只能在队尾删除 -- 后进后出 表尾称为栈顶:表头称为栈底 插入元素到栈 ...

  7. usage: git remote add [<options>] <name> <url> -f, --fetch fetch the remote branches --tags import all tags and associated objects when fetching

    按照git官网提示输入 git pushgit remote add origin git@github.com:***3 / elm-1.git -u 链接git远程仓库 出现错误 usage: g ...

  8. 题解【洛谷P2341】 [HAOI2006]受欢迎的牛

    题面 题解 \(Tarjan\)缩点后统计每个点的出度. 如果有多个点出度为\(0\),就直接输出\(0\),否则输出出度为\(0\)的强连通分量里的点数. 代码 #include <iostr ...

  9. 新手学习PHP的避雷针,这些坑在PHP开发中就别跳了

    不要!用记事本编辑php文件 早些年能用记事本编程是一些人自我吹嘘的资本,能用记事本编程就是牛逼的代名词.但是这里要告诫大家的是,千万不要使用Windows自带的记事本编辑任何文本文件.用Window ...

  10. scrapy 框架基本使用

    scrapy简介: Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓取 ...