Go语言数据结构-栈

定义

栈是一种先入后出的有序列表。限制了线性表中元素的插入和删除只能在线性表的同一端进行。允许插入和删除的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom)。

应用场景

  1. 子程序的调用:在切换到子程序前,先将下一个指令的地址存入堆栈中,指导子程序处理完成再将地址取出,回到原来的程序。
  2. 处理递归调用:调用递归函数之前,先将下一个指令的地址,参数,区域变量等数据存入堆栈中。
  3. 表达式的转换和求值。
  4. 二叉树的便历。
  5. 图形的深度优化搜索法。

基本结构和操作

type Stack struct {
   MaxTop int    //栈最大可以存放的数的个数
   Top    int    //表示栈顶的索引id,初始值为-1,最大值为MaxTop-1
   arr    [5]int //数组模拟栈
}

入栈

func (s *Stack) Push(val int) error {
	if s.Top == s.MaxTop-1 {
		return errors.New("栈满了")
	}

	s.Top++
	s.arr[s.Top] = val

	return nil
}

出栈

func (s *Stack) Pop() (int, error) {
	if s.Top == -1 {
		return 0, errors.New("空栈")
	}

	res := s.arr[s.Top]
	s.arr[s.Top] = 0
	s.Top--
	return res, nil
}

便历

func (s *Stack) List() {
	if s.Top == -1 {
		fmt.Println("空栈")
	}
	for i := 0; i < s.Top+1; i++ {
		fmt.Printf("arr[%v]=%v\n", i, s.arr[i])
	}
}

汇总

package main

import (
	"errors"
	"fmt"
)

type Stack struct {
	MaxTop int    //栈最大可以存放的数的个数
	Top    int    //表示栈顶,因为栈顶固定,因此我们可以直接使用Top
	arr    [5]int //数组模拟栈
}

func main() {
	myStack := Stack{
		MaxTop: 5,
		Top:    -1, //默认值,栈为空
	}
	myStack.Push(1)
	myStack.Push(4)
	myStack.Push(9)
	fmt.Println("top是:", myStack.Top)
	myStack.List()

	fmt.Println("开始pop1个")
	val, _ := myStack.Pop()
	fmt.Println("top是:", myStack.Top)
	fmt.Println("pop值:", val)
	myStack.List()

	fmt.Println("再pop1个")
	val2, _ := myStack.Pop()
	fmt.Println("top是:", myStack.Top)
	fmt.Println("pop值:", val2)
	myStack.List()

	fmt.Println("再pop1个")
	val3, _ := myStack.Pop()
	fmt.Println("top是:", myStack.Top)
	fmt.Println("pop值:", val3)
	myStack.List()

}

func (s *Stack) Push(val int) error {
	if s.Top == s.MaxTop-1 {
		return errors.New("栈满了")
	}

	s.Top++
	s.arr[s.Top] = val

	return nil
}

func (s *Stack) Pop() (int, error) {
	if s.Top == -1 {
		return 0, errors.New("空栈")
	}

	res := s.arr[s.Top]
	s.arr[s.Top] = 0
	s.Top--
	return res, nil
}

func (s *Stack) List() {
	if s.Top == -1 {
		fmt.Println("空栈")
	}
	for i := 0; i < s.Top+1; i++ {
		fmt.Printf("arr[%v]=%v\n", i, s.arr[i])
	}
}

案例

栈实现综合计算器

思路
  1. 创建两个栈分别报错数字和操作符号
  2. 遍历运算式字符串,如果是一个数字,直接压入数字栈
  3. 如果是一个运算符,且运算符栈为空栈,则直接入栈
  4. 如果是一个运算符,且运算符栈不为空,如果运算符栈栈顶元素的运算符优先级大于即将入栈的运算符优先级,则在数字栈中pop出2个数字,在运算符栈pop一个运算符,做运算,结果压入数字栈中,再把运算符压入运算符栈;否则直接入符号栈
  5. 运算式遍历完成,遍历符号栈,pop一个数,数字栈pop2个数字,做运算,然后把结果压入数字栈中,直到遍历完成
  6. pop出数字栈的数即为运算结果
代码实现:
package main

import (
	"errors"
	"fmt"
	"strconv"
	"unicode"
)

type Stack struct {
	MaxTop int     //栈最大可以存放的数的个数
	Top    int     //表示栈顶
	arr    [20]int //数组模拟栈
}

var itobMap = map[int]byte{
	1: '+',
	2: '-',
	3: '*',
	4: '/',
}
var btoiMap = map[byte]int{
	'+': 1,
	'-': 2,
	'*': 3,
	'/': 4,
}

var opePriorityMap = map[byte]int{
	'+': 1,
	'-': 1,
	'*': 2,
	'/': 2,
}

func main() {
	expStr := "3+2*6-2"
	expStrArr := []byte(expStr)
	a := operation(expStrArr)
	fmt.Println(a)

}

func (s *Stack) Push(val int) error {
	if s.Top == s.MaxTop-1 {
		return errors.New("栈满了")
	}

	s.Top++
	s.arr[s.Top] = val

	return nil
}

func (s *Stack) Pop() (int, error) {
	if s.Top == -1 {
		return 0, errors.New("空栈")
	}

	res := s.arr[s.Top]
	s.arr[s.Top] = 0
	s.Top--
	return res, nil
}

func (s *Stack) List() {
	if s.Top == -1 {
		fmt.Println("空栈")
	}
	for i := 0; i < s.Top+1; i++ {
		fmt.Printf("arr[%v]=%v\n", i, s.arr[i])
	}
}

func operation(expStr []byte) int {
	numStack := Stack{
		MaxTop: 20,
		Top:    -1,
	}
	opeStack := Stack{
		MaxTop: 20,
		Top:    -1,
	}
	//入栈
	for _, v := range expStr {
		vInt, _ := strconv.Atoi(string(v))
		if unicode.IsDigit(rune(v)) {
			numStack.Push(vInt)
		} else {
			if opeStack.Top == -1 {
				opeStack.Push(btoiMap[v])
			} else {
				if opeStack.arr[opeStack.Top] >= opePriorityMap[v] {
					opeVal, _ := opeStack.Pop()
					numVal2, _ := numStack.Pop()
					numVal1, _ := numStack.Pop()
					resTmp := simpleOpe(numVal1, numVal2, itobMap[opeVal])
					numStack.Push(resTmp)
					opeStack.Push(btoiMap[v])
				} else {
					opeStack.Push(btoiMap[v])
				}
			}
		}
	}
	//符号出栈
	for opeStack.Top >= 0 {
		opeTmp, _ := opeStack.Pop()
		numVal2, _ := numStack.Pop()
		numVal1, _ := numStack.Pop()
		resTmp := simpleOpe(numVal1, numVal2, itobMap[opeTmp])
		numStack.Push(resTmp)
	}

	res, _ := numStack.Pop()
	return res
}

func simpleOpe(a, b int, operation byte) int {
	if operation == '+' {
		return a + b
	} else if operation == '-' {
		return a - b
	} else if operation == '*' {
		return a * b
	} else {
		return a / b
	}
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值