逆波兰表达式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)
		}
	
	}
posted @ 2013-04-24 10:41  零界寒冰  阅读(187)  评论(0编辑  收藏  举报