逆波兰表达式(中缀转后缀表达式) ##一 问题描述 解析并计算 9+(3-1)*3+10/2 为后缀表达式 [9,3,1,-,3,*,+,10,2,/,+ ] 中缀转后缀 ###1 描述: 在我们转换中缀到后缀的过程,其实是一个取出表达式中的操作数或运算符号进行重排列的过程。 主要的转换都是根据运算符号来进行的,从表达式中取出来的数字都会放入栈中,然后根据取出来运算符号来解析出新表达式。 但是运算符号其实也有一个优先级,低优先级的符号应该比高优先级符号的解析优先级别要低,也就是先解析高优先级符号,然后才会解析低优先级符号。 比如 9+2*3,此时应该先解析*也就是 2,3,* 然后才会解析 + 。最终结果为: 9 2 3 * + 因此在解析符号的时候会做一个判断,根据优先级来判断是否立即解析还是继续将符号入栈。 关于操作符优先级: 1)其中(最高,)最低。按顺序为: ( > * , / > + ,- > ) > # 2)运算符在栈内优先级(isp)和栈外优先级(icp)的计算优先级是相反的 。 3)最后为了简化栈判断,我们加了一个标志位,假设该栈中有一个最低优先级的特殊符号“#”。 各运算符及符号优先级:参见 [http://baike.baidu.com/view/552648.htm](http://baike.baidu.com/view/552648.htm) ##2 算法分析 从左到右遍历,如果是操作数则输出。 如果是运算符号,判断与栈顶符号的优先级,高于栈顶符号直接进栈。 否则,栈顶符号出栈。继续出栈知道栈顶运算符的优先级低于当前运算符。 然后将当前预算符入栈。 若当前运算符为'(',直接入栈; 若为')',出栈并顺序输出运算符直到遇到第一个'(',遇到的第一个'('出栈但不输出; 若为四则运算符,比较栈顶元素与当前元素的优先级: 如果 栈顶元素运算符优先级 >= 当前元素的优先级,出栈并顺序输出运算符直到 栈顶元素优先级 < 当前元素优先级,然后当前元素入栈; 如果 栈顶元素 < 当前元素,直接入栈。 ###3 go语言实现 package main import ( "fmt" ) /* * 定义节点 */ type Node struct { Data string Next *Node } /* * 定义栈 */ type Stack struct { Top *Node Length int } func NewStack() *Stack { return &Stack{Top: nil, Length: 0} } /* * 压栈 */ func (list *Stack) Push(data string) error { node := &Node{Data: data, Next: list.Top} list.Top = node list.Length++ return nil } /* * 出栈 */ func (list *Stack) Pop() (string, error) { if list.Length == 0 { return "", fmt.Errorf("the list is empty") } node := list.Top list.Top = node.Next list.Length-- return node.Data, nil } /**************************************************/ //栈外优先级icp(In coming priority) func GetIcp(oper string) int { switch oper { case ")": return 1 case "(": return 8 case "+": fallthrough case "-": return 2 case "*": fallthrough case "/": fallthrough case "%": return 4 case "#": return 0 } return 0 } //栈内优先级isp(In stack priority) func GetIsp(oper string) int { switch oper { case ")": return 8 case "(": return 1 case "+": fallthrough case "-": return 3 case "*": fallthrough case "/": fallthrough case "%": return 5 case "#": return 0 } return 0 } func IsOperator(oper string) bool { switch oper { case "(": fallthrough case ")": fallthrough case "+": fallthrough case "-": fallthrough case "*": fallthrough case "/": return true default: return false } return false } func CenterToEnd(expr []string) []string { stack := &Stack{Top: &Node{Data: "#", Next: nil}, Length: 0} retexpr := make([]string, 0) for _, v := range expr { if !IsOperator(v) { retexpr = append(retexpr, v) } else { if stack.Length == 0 { stack.Push(v) } else { //遇到")",则出栈并输出。直到"(","("出栈不输出。 if GetIcp(v) == 1 { for GetIcp(stack.Top.Data) != 8 { data, _ := stack.Pop() retexpr = append(retexpr, data) } stack.Pop() } else if GetIcp(v) >= GetIsp(stack.Top.Data) { //比较运算符>的情况 stack.Push(v) } else { //比较运算符<=的情况 for GetIcp(v) < GetIsp(stack.Top.Data) { data, _ := stack.Pop() retexpr = append(retexpr, data) } stack.Push(v) } } } } //输出栈中剩余计算符 for stack.Length > 0 { data, _ := stack.Pop() retexpr = append(retexpr, data) } return retexpr } func main() { expr := []string{"9", "+", "(", "3", "-", "1", ")", "*", "3", "+", "10", "/", "2"} retexpr := CenterToEnd(expr) for _, v := range retexpr { fmt.Println("value=========", v) } }