青训营笔记:GO算法之Stack

76 阅读1分钟

使用栈实现计算器

package main

import (
	"fmt"
	"strconv"
)

func main() {
	expression := "1919+222-22321/222"
	numStack := NewArrayStack2(10)
	operStack := NewArrayStack2(10)
	index := 0
	num1 := 0
	num2 := 0
	oper := rune(0)
	res := 0
	var ch rune
	keepNum := "" //拼接多位数
	for index < len(expression) {
		ch = rune(expression[index])
		if operStack.isOper(ch) { //如果是运算符
			if !operStack.isEmpty() { //非空
				if operStack.priority(ch) <= operStack.priority(operStack.peak()) {
					//如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数,
					//在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈
					num1 = numStack.pop()
					num2 = numStack.pop()
					oper = rune(operStack.pop())
					res = numStack.cal(num1, num2, oper)
					//结果入数栈
					numStack.push(res)
					//当前操作符入符号栈
					operStack.push(int(ch))
				} else { //当前符号优先级若大于上一个符号,直接入栈
					operStack.push(int(ch))
				}
			} else {
				//如果符号栈为空,直接入栈
				operStack.push(int(ch))
			}
		} else {
			//如果是数字
			keepNum += string(ch)
			//如果ch已经是expression的最后一位,就直接入栈
			if index == len(expression)-1 {
				num, _ := strconv.Atoi(keepNum)
				numStack.push(num)
			} else {
				//判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈
				if operStack.isOper(rune(expression[index+1])) {
					num, _ := strconv.Atoi(keepNum)
					numStack.push(num)
					keepNum = ""
				}
			}
		}
		index++
		if index >= len(expression) {
			break
		}
	}
	for {
		if operStack.isEmpty() {
			break
		}
		num1 = numStack.pop()
		num2 = numStack.pop()
		oper = rune(operStack.pop())
		res = numStack.cal(num1, num2, oper)
		numStack.push(res)
	}
	res2 := numStack.pop()
	fmt.Printf("表达式 %s = %d", expression, res2)
}

构造函数

type ArrayStack2 struct {
	maxsize int
	stack   []int
	top     int
}
// NewArrayStack2 构建函数
func NewArrayStack2(maxsize int) *ArrayStack2 {
	return &ArrayStack2{
		maxsize,
		make([]int, maxsize),
		-1,
	}
}

判断是否空栈

// isEmpty 栈是否为空
func (a *ArrayStack2) isEmpty() bool {
	return a.top == -1
}

入栈

// push
func (a *ArrayStack2) push(value int) {
	if a.top == a.maxsize-1 {
		fmt.Print("栈满无法添加")
		return
	}
	a.top++
	a.stack[a.top] = value
}

出栈

// pop
func (a *ArrayStack2) pop() int {
	if a.isEmpty() {
		panic("栈空无数据")
	}
	value := a.stack[a.top]
	a.top--
	return value
}

查看栈顶的元素

// peak
func (a *ArrayStack2) peak() rune {
	if a.isEmpty() {
		panic("栈空无数据")
	}
	return rune(a.stack[a.top])
}

打印

// list
func (a *ArrayStack2) list() {
	if a.isEmpty() {
		panic("栈空")
	}
	for i, v := range a.stack[:a.top+1] {
		fmt.Printf("stack[%d]=%d\n", i, v)
	}
}

判断运算符的优先级的方法,以便计算时调用

// priority
func (a ArrayStack2) priority(oper rune) int {
	switch oper {
	case '*', '/':
		return 1
	case '+', '-':
		return 0
	default:
		return -1 // 假定目前的表达式只有 +, - , * , /
	}
}

判断是否为符号 返回bool值

// isOper
func (a ArrayStack2) isOper(val rune) bool {
	return val == '+' || val == '-' || val == '*' || val == '/'
}

下面是计算方法,传入num,oper 传出int类型的结果

使用switch来实现


// cal
func (a ArrayStack2) cal(num1, num2 int, oper rune) int {
	res := 0
	switch oper {
	case '+':
		res = num1 + num2
	case '-':
		res = num2 - num1
	case '*':
		res = num1 * num2
	case '/':
		res = num2 / num1
	}
	return res
}