zoukankan      html  css  js  c++  java
  • 逆波兰表达式2中缀转后缀表达式)

    	逆波兰表达式(中缀转后缀表达式)
    
    ##一 问题描述
    解析并计算 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)
    		}
    	
    	}
    
  • 相关阅读:
    java反射——字段
    java反射——方法
    java反射——构造方法
    代构建高可用分布式系统的利器——Netty
    JavaEE复习计划
    Java基础复习计划(三)
    Java基础复习计划(二)
    Java基础复习计划
    关于内网穿透的相关内容
    Docker化你的应用
  • 原文地址:https://www.cnblogs.com/sxt102400/p/3039676.html
Copyright © 2011-2022 走看看