golang实现中缀表达式转换成后缀表达式(逆波兰)

NifixToRPN函数只能转换无括号的中缀表达式,遇到括号则调用barket函数,如果括号中嵌套括号则形成了递归。

支持含 + - * / ( ) 与 整数 组合的中缀表达式转换( 可以支持负数如(-2) )。

函数预览:

func NifixToRPN(nifix []byte) []string

Go语言实现:

package main

import "fmt"

//与NifixToRPN 递归消除括号,返回对应后括号的位置
func barket(a []byte, first int) ([]string, int) {
	last := 0  //对应后括号的位置
	count := 0 //计数左括号
	for i := first; i < len(a)-1; i++ {
		if a[i+1] == '(' {
			count++
		}
		if a[i+1] == ')' {
			if count == 0 {
				last = i + 1
                break
			} else {
				count--
			}
		}
	}
	NewA := a[first+1 : last]
	return NifixToRPN(NewA), last //递归
}

//中缀表达式转后缀表达式
//仅仅支持含 + - * / ( ) 与 整数 组合的表达式(可以支持负数如(-2))
func NifixToRPN(nifix []byte) []string {
	operatorStack := make([]byte, 0, 20) //存放运算符的栈(切片模拟栈)
	ret := make([]string, 0, len(nifix)) //返回的逆波兰表达式
	//把'+' '-'看成一类,优先级低于 '*' '/'
	priority := map[byte]int{
		'+': 0,
		'-': 0,
		'*': 1,
		'/': 1,
	}
	i := 0
	//处理第一个数为负数的情况
	if nifix[0] == '-' {
		i = 1
		tempI := i
		//处理'-'后的数字加入ret
		for tempI+1 < len(nifix) && nifix[tempI+1] >= '0' && nifix[tempI+1] <= '9' {
			tempI++
		}
		ret = append(ret, "-"+string(nifix[i:tempI+1]))
		i = tempI + 1
	}
	for ; i < len(nifix); i++ {
		//将连续的数字写入ret
		if nifix[i] >= '0' && nifix[i] <= '9' {
			tempI := i
			for tempI+1 < len(nifix) && nifix[tempI+1] >= '0' && nifix[tempI+1] <= '9' {
				tempI++
			}
			ret = append(ret, string(nifix[i:tempI+1]))
			i = tempI
			continue
		}
		//把括号里面的内容当成一个数字,将得到的逆波兰表达式直接写入ret
		if nifix[i] == '(' {
			//调用barket消除括号
			newNifix, last := barket(nifix, i)
			ret = append(ret, newNifix...)
			i = last
			continue
		}
		//栈中没有运算符,直接将当前运算符入栈
		if len(operatorStack) == 0 {
			operatorStack = append(operatorStack, nifix[i])
			continue
		}
		//如果当前符号的优先级 小于 上一个未出栈符号优先级,则将栈清空,当前符号入栈
		if priority[nifix[i]] < priority[operatorStack[len(operatorStack)-1]] {
			//将栈清空,写入ret
			for len(operatorStack) != 0 {
				ret = append(ret, string(operatorStack[len(operatorStack)-1]))
				operatorStack = operatorStack[0 : len(operatorStack)-1]
			}
			//当前符号入栈
			operatorStack = append(operatorStack, nifix[i])
			continue
		}
		//如果当前符号的优先级 等于 上一个未出栈符号优先级,栈中优先级相同的连续符号全部出栈,当前符号入栈
		if priority[nifix[i]] == priority[operatorStack[len(operatorStack)-1]] {
			for len(operatorStack) != 0 && priority[nifix[i]] == priority[operatorStack[len(operatorStack)-1]] {
				ret = append(ret, string(operatorStack[len(operatorStack)-1]))
				operatorStack = operatorStack[0 : len(operatorStack)-1]
			}
			//当前符号入栈
			operatorStack = append(operatorStack, nifix[i])
			continue
		}
		//此时栈中还有符号,且当前符号优先级高于栈中符号,将当前符号入栈
		operatorStack = append(operatorStack, nifix[i])
	}
	//还有未出栈的符号,依次出栈
	if len(operatorStack) != 0 {
		if len(operatorStack) == 2 {
			ret = append(ret, string(operatorStack[1]))
		}
		ret = append(ret, string(operatorStack[0]))
	}
	return ret
}


func main() {
	//test case
	//s1:="1+2*6-3"
	//s1 := "1+(2-3)*4+10/5"
	//s1 := "1+((2+3)*4)-5"
	//s1 := "15*90+2*1/6-3"
	//s1 := "2*4/7-3/6+9"
	s1 := "15*90+2*1/6-3-1+((2+3)*4)-9+(2-3)*4"
	ss := NifixToRPN([]byte(s1))
	fmt.Println(s1)
	fmt.Println(ss)
}

test case输出

15*90+2*1/6-3-1+((2+3)*4)-9+(2-3)*4
[15 90 * 2 1 * 6 / + 3 - 1 - 2 3 + 4 * + 9 - 2 3 - 4 * +]

golang测试代码:

package main

import (
	"reflect"
	"testing"
)

type testcase struct {
	Nifix string
	RPN   []string
}

func TestNifixToRPN(t *testing.T) {
	tests := []testcase{
		{"1+2*6*4-3", []string{"1", "2", "6", "*", "4", "*", "+", "3", "-"}},
		{"-366/3+9", []string{"-366", "3", "/", "9", "+"}},
		{"(-366/3+9)", []string{"-366", "3", "/", "9", "+"}},
		{"-3/3+9", []string{"-3", "3", "/", "9", "+"}},
		{"-3", []string{"-3"}},
		{"(-3)", []string{"-3"}},
		{"(-366)", []string{"-366"}},
		{"1+2+6-3*9", []string{"1", "2", "+", "6", "+", "3", "9", "*", "-"}},
		{"1*8*9+2*6-3+5", []string{"1", "8", "*", "9", "*", "2", "6", "*", "+", "3", "-", "5", "+"}},
		{"1*8*9*7/2+2/3*6-3+5", []string{"1", "8", "*", "9", "*", "7", "*", "2", "/", "2", "3", "/",
			"6", "*", "+", "3", "-", "5", "+"}},
		{"1/8*9+2+6-3*5", []string{"1", "8", "/", "9", "*", "2", "+", "6", "+", "3", "5", "*", "-"}},
		{"2*6-3", []string{"2", "6", "*", "3", "-"}},
		{"1+(2-3)*4+10/5", []string{"1", "2", "3", "-", "4", "*", "+", "10", "5", "/", "+"}},
		{"1+2*3-4-5/6", []string{"1", "2", "3", "*", "+", "4", "-", "5", "6", "/", "-"}},
		{"1+((2+3)*4)-5", []string{"1", "2", "3", "+", "4", "*", "+", "5", "-"}},
		{"1+(-9*(2+3)*4)-5", []string{"1", "-9", "2", "3", "+", "*", "4", "*", "+", "5", "-"}},
		{"1+(-99*(2+3)*4+5)-5", []string{"1", "-99", "2", "3", "+", "*", "4", "*", "5", "+", "+", "5", "-"}},
		{"15*90+2*1/6-3", []string{"15", "90", "*", "2", "1", "*", "6", "/", "+", "3", "-"}},
		{"15*90+4*(2-(6+9)*3)", []string{"15", "90", "*", "4", "2", "6", "9", "+", "3", "*", "-", "*", "+"}},
		{"15*90+4*(-2-(6+9)*3)", []string{"15", "90", "*", "4", "-2", "6", "9", "+", "3", "*", "-", "*", "+"}},
		{"15*(100-90)+2", []string{"15", "100", "90", "-", "*", "2", "+"}},
		{"2*4/7-3/6+9", []string{"2", "4", "*", "7", "/", "3", "6", "/", "-", "9", "+"}},
		{"15*90+2*1/6-3-1+((2+3)*4)-9+(2-3)*4", []string{"15", "90", "*", "2", "1", "*", "6", "/", "+", "3", "-", "1",
			"-", "2", "3", "+", "4", "*", "+", "9", "-", "2", "3", "-", "4", "*", "+"}},
		{"15*90+2*1/6-3-1+((2+3)*4)-9+99*(2-3)*4", []string{"15", "90", "*", "2", "1", "*", "6", "/", "+", "3", "-", "1",
			"-", "2", "3", "+", "4", "*", "+", "9", "-", "99", "2", "3", "-", "*", "4", "*", "+"}},
		{"3*75+4-8+((10*(6/((9+3)*(0-11))))+17)+5", []string{"3", "75", "*", "4", "+", "8", "-", "10", "6", "9", "3", "+", "0", "11",
			"-", "*", "/", "*", "17", "+", "+", "5", "+"}},
		{"3*75+4-8+((10*(6/((9+3)*(0-11))))*99+17)*99+5", []string{"3", "75", "*", "4", "+", "8", "-", "10", "6", "9", "3", "+", "0", "11",
			"-", "*", "/", "*", "99", "*", "17", "+", "99", "*", "+", "5", "+"}},
		{"(3*75+4-8+((10*(6/((9+3)*(0-11))))*99+17)*99+5)", []string{"3", "75", "*", "4", "+", "8", "-", "10", "6", "9", "3", "+", "0", "11",
			"-", "*", "/", "*", "99", "*", "17", "+", "99", "*", "+", "5", "+"}},
		{"3*75+4-8+((10*(-6/((9+3)*(0-11))))*99+17)*99+5", []string{"3", "75", "*", "4", "+", "8", "-", "10", "-6", "9", "3", "+", "0", "11",
			"-", "*", "/", "*", "99", "*", "17", "+", "99", "*", "+", "5", "+"}},
	}
	for _, v := range tests {
		if !reflect.DeepEqual(NifixToRPN([]byte(v.Nifix)), v.RPN) {
			t.Errorf("input:%s\n", v.Nifix)
			t.Errorf("want:%v\n", v.RPN)
			t.Errorf("get:%v\n", NifixToRPN([]byte(v.Nifix)))
		}
	}
}

测试用例全部通过:

=== RUN   TestNifixToRPN
--- PASS: TestNifixToRPN (0.00s)
PASS
ok      2       0.054s

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值