有些程序员也把栈称为堆栈,即栈和堆栈是同一个概念
package main
import (
"errors"
"fmt"
)
// 用数组模拟栈的使用
type Stack struct {
MaxTop int // 表示栈最大可以存放的数据的个数
Top int // 表示栈顶 栈顶是固定的,因此可以不用设置
arr [5]int // 数组模拟栈
}
// 入栈
func (s *Stack) Push(val int) (err error) {
// 先判断栈是否已经满了
if s.Top == s.MaxTop-1 {
fmt.Println("栈已经满了!")
return errors.New("stack full")
}
s.Top++
// 放入数据
s.arr[s.Top] = val
return
}
func main() {
stack := &Stack{
MaxTop: 5,
Top: -1,
}
// 入栈
stack.Push(1)
stack.Push(2)
stack.Push(3)
stack.Push(4)
stack.Push(5)
}
package main
import (
"errors"
"fmt"
)
// 用数组模拟栈的使用
type Stack struct {
MaxTop int // 表示栈最大可以存放的数据的个数
Top int // 表示栈顶 栈顶是固定的,因此可以不用设置
arr [5]int // 数组模拟栈
}
// 入栈
func (s *Stack) Push(val int) (err error) {
// 先判断栈是否已经满了
if s.Top == s.MaxTop-1 {
fmt.Println("栈已经满了!")
return errors.New("stack full")
}
s.Top++
// 放入数据
s.arr[s.Top] = val
return
}
// 遍历栈,需要从栈顶开始遍历
func (s *Stack) List() {
// 判断是否为空栈
if s.Top == -1 {
fmt.Println("stack empty!")
return
}
fmt.Println("栈的遍历输出结果如下:")
for i := s.Top; i >= 0; i-- {
fmt.Printf("arr[%d]=%d\n", i, s.arr[i])
}
}
func main() {
stack := &Stack{
MaxTop: 5,
Top: -1,
}
// 入栈
stack.Push(1)
stack.Push(2)
stack.Push(3)
stack.Push(4)
stack.Push(5)
stack.Push(6)
// 遍历
stack.List()
}
运行结果:
[Running] go run "e:\golang开发学习\go_pro\test.go"
栈已经满了!
栈的遍历输出结果如下:
arr[4]=5
arr[3]=4
arr[2]=3
arr[1]=2
arr[0]=1
[Done] exited with code=0 in 1.266 seconds
package main
import (
"errors"
"fmt"
)
// 用数组模拟栈的使用
type Stack struct {
MaxTop int // 表示栈最大可以存放的数据的个数
Top int // 表示栈顶 栈顶是固定的,因此可以不用设置
arr [5]int // 数组模拟栈
}
// 入栈
func (s *Stack) Push(val int) (err error) {
// 先判断栈是否已经满了
if s.Top == s.MaxTop-1 {
fmt.Println("栈已经满了!")
return errors.New("stack full")
}
s.Top++
// 放入数据
s.arr[s.Top] = val
return
}
// 出栈
func (s *Stack) Pop() (val int, err error) {
// 先判断栈是否为空
if s.Top == -1 {
fmt.Println("stack empty!")
return 0, errors.New("stack empty")
}
// 先取值 再 s.Top
val = s.arr[s.Top]
s.Top--
return val, nil
}
// 遍历栈,需要从栈顶开始遍历
func (s *Stack) List() {
// 判断是否为空栈
if s.Top == -1 {
fmt.Println("stack empty!")
return
}
fmt.Println("栈的遍历输出结果如下:")
for i := s.Top; i >= 0; i-- {
fmt.Printf("arr[%d]=%d\n", i, s.arr[i])
}
}
func main() {
stack := &Stack{
MaxTop: 5,
Top: -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)
// 显示
stack.List()
}
运行结果:
[Running] go run "e:\golang开发学习\go_pro\test.go"
栈的遍历输出结果如下:
arr[4]=5
arr[3]=4
arr[2]=3
arr[1]=2
arr[0]=1
出栈 val= 5
栈的遍历输出结果如下:
arr[3]=4
arr[2]=3
arr[1]=2
arr[0]=1
[Done] exited with code=0 in 1.251 seconds
思路分析:
代码实现:
package main
import (
"errors"
"fmt"
"strconv"
)
// 用数组模拟栈的使用
type Stack struct {
MaxTop int // 表示栈最大可以存放的数据的个数
Top int // 表示栈顶 栈顶是固定的,因此可以不用设置
arr [5]int // 数组模拟栈
}
// 入栈
func (s *Stack) Push(val int) (err error) {
// 先判断栈是否已经满了
if s.Top == s.MaxTop-1 {
fmt.Println("栈已经满了!")
return errors.New("stack full")
}
s.Top++
// 放入数据
s.arr[s.Top] = val
return
}
// 出栈
func (s *Stack) Pop() (val int, err error) {
// 先判断栈是否为空
if s.Top == -1 {
fmt.Println("stack empty!")
return 0, errors.New("stack empty")
}
// 先取值 再 s.Top
val = s.arr[s.Top]
s.Top--
return val, nil
}
// 遍历栈,需要从栈顶开始遍历
func (s *Stack) List() {
// 判断是否为空栈
if s.Top == -1 {
fmt.Println("stack empty!")
return
}
fmt.Println("栈的遍历输出结果如下:")
for i := s.Top; i >= 0; i-- {
fmt.Printf("arr[%d]=%d\n", i, s.arr[i])
}
}
// 判断一个字符是否为运算符 这里只做 [+ - * /]
func (s *Stack) IsOper(val int) bool {
// 这里通过ASCII值比较
if val == 42 || val == 43 || val == 45 || val == 47 {
return true
} else {
return false
}
}
// 运算的方法
func (s *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
}
// 定义一个方法 返回运算符的优先级 (这个定级是我们自己定的 底层也是这样实现的)
func (s *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 := "300+2*6-2"
// 定义一个index帮助我们扫描表达式
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) {
// 说明是符号
// 空栈直接入栈
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()
// 注意下num的顺序即可
result = operStack.Cal(num1, num2, oper)
// 将计算结果 重新压入数栈中
numStack.Push(result)
// 将当前的符号压入符号栈
operStack.Push(temp)
} else {
operStack.Push(temp)
}
}
} else {
// 这里不能直接压 因为它压的是 3的ASCII 51
// 处理多位数的思路
// 1. 先定义一个变量 keynum, 用来做拼接的
// 2. 每次要向index后的字符 下探以为 判断是否运算符在做处理
// 已经到最后一位 直接拼入就可以了
keepNum += ch
if index == len(exp)-1 {
val, _ := strconv.ParseInt(keepNum, 10, 64)
numStack.Push(int(val))
} else {
// 向index后面探测一位 后面一位是操作符
if operStack.IsOper(int([]byte(exp[index+1 : index+2])[0])) {
val, _ := strconv.ParseInt(keepNum, 10, 64)
numStack.Push(int(val))
keepNum = ""
}
}
}
// 继续扫描
if index+1 == len(exp) {
break
}
index++
}
//如果扫描表达式完毕,依次从符号栈取出符号,然后从数栈取出两个数,
//运算后的结果,入数栈,直到符号栈为空
for {
if operStack.Top == -1 {
// 符号栈为空 退出
break
}
num1, _ = numStack.Pop()
num2, _ = numStack.Pop()
oper, _ = operStack.Pop()
// 注意下num的顺序即可
result = operStack.Cal(num1, num2, oper)
// 将计算结果 重新压入数栈中
numStack.Push(result)
}
// 如果我们的算法没有问题,表达式也是正确的,则结果就是numStack最后数
res, _ := numStack.Pop()
fmt.Printf("表达式%s= %v\n", exp, res)
}
运行结果:
[Running] go run "e:\golang开发学习\go_pro\test.go"
表达式300+2*6-2= 310
[Done] exited with code=0 in 1.41 seconds