阅读目录
一、栈介绍
二、栈应用
一、栈介绍
二、栈应用
计算表达式
package main
import (
"errors"
"fmt"
"strconv"
)
type Stack struct {
maxTop int
top int
arr [20]int //数组
}
func (this *Stack) Push(val int) (err error) {
// 首先判断栈已满
if this.top == this.maxTop-1 {
return errors.New("stack full")
}
// top++ -> 移动top值
this.top++
this.arr[this.top] = val
return
}
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]=%v", i, this.arr[i])
}
}
func (this *Stack) Pop() (val int, err error) {
if this.top == -1 {
fmt.Println("stack empty")
return -1, errors.New("stack empty")
}
val = this.arr[this.top]
this.top-- // 移动栈顶
return val, nil
}
func main() {
//数字栈
numStack := &Stack{
maxTop: 20,
top: -1,
}
//符号栈
operStack := &Stack{
maxTop: 20,
top: -1,
}
exp := "3+20*12-2"
// 定义一个index,帮助扫描exp
index := 0
num1 := 0
num2 := 0
oper := 0
keepNum := "" // 拼接字符串
for {
//处理多位数问题
ch := exp[index : index+1]
tmp := int([]byte(ch)[0]) //转为ascii值
if operStack.isOper(tmp) {
// 判断空栈
if operStack.top == -1 {
_ = operStack.Push(tmp)
} else {
//第一种情况 栈顶元素优先级大于入栈元素 则 计算后在写入栈
if operStack.Priority(operStack.arr[operStack.top]) >= operStack.Priority(tmp) {
num1, _ = numStack.Pop() //取出栈顶元素1
num2, _ = numStack.Pop() //取出栈顶元素2
//先处理大的优先级
oper, _ = operStack.Pop() //取出符号元素
newVal := operStack.Cal(num1, num2, oper) //计算
_ = numStack.Push(newVal) // 计算值写入栈
//新的表达式入栈
_ = operStack.Push(tmp)
} else {
//第二种情况
_ = operStack.Push(tmp)
}
}
} else {
//拼接
keepNum += ch
// 如果已经到表达式最后
if index == len(exp)-1 {
numVal, _ := strconv.ParseInt(keepNum, 10, 64)
_ = numStack.Push(int(numVal))
} else {
//如果不是最后 向index后字符探测一位
if operStack.isOper(int([]byte(exp[index+1 : index+2])[0])) {
numVal, _ := strconv.ParseInt(keepNum, 10, 64)
_ = numStack.Push(int(numVal))
keepNum = "" //清空标记
}
}
}
//继续扫描
if index+1 != len(exp) {
index++
} else {
break
}
}
// 最后一步处理出栈计算
for {
if operStack.top == -1 {
break
}
num1, _ = numStack.Pop() //取出栈顶元素1
num2, _ = numStack.Pop() //取出栈顶元素2
//先处理大的优先级
oper, _ = operStack.Pop() //取出符号元素
newVal := numStack.Cal(num1, num2, oper) //计算
_ = numStack.Push(newVal) // 计算值写入栈
}
// 结束后 栈中只存在最后一个计算值
result, _ := numStack.Pop()
fmt.Println("计算的值为:", result)
}
//
func (this *Stack) isOper(val int) bool {
// 42->* 43->
if val == 42 || val == 43 || val == 45 || val == 47 {
return true
}
return false
}
//计算方法
func (this *Stack) Cal(num1, num2, oper int) int {
res := 0
switch oper {
case 42:
res = num2 * num1
case 43:
res = num1 + num2
case 45:
res = num2 - num1
case 47:
res = num2 / num1
default:
fmt.Println("运算符错误", oper)
}
return res
}
//返回优先级方法 +- => 0 */ => 1
func (this *Stack) Priority(oper int) int {
if oper == 42 || oper == 47 {
return 1
} else if oper == 43 || oper == 45 {
return 0
}
return -1
}