后缀表达式

为什么使用后缀表达式:

后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后,就比如中缀表达式12+3*4-5,后缀表达式为12  3  4  *  +  5   -  。转换成这种表达式之后,计算结果的过程就会容易的多。

下面是得到后缀表达式后,是怎么运算的,通过这个可以看到为什么使用后缀表达式。

后缀表达式中的各个数据

12

3

4

*

+

5

-

计算过程将会使用到栈这种数据结构,具体过程为。

依次得到后缀表达式中的每一个元素,执行下列两个操作。

1.当遇到数据就入栈。比如第一个数是12 ,说明12入栈。第二个数也入栈,依次直到遇到运算符,进行2步骤。

入栈的数据

4

3

12

2.当遇到运算符就出栈,并将栈顶的两个数据取出,进行运算,将运算结果入栈。比如当前的3 、4 取出,进行乘法运算,得到12,将12入栈。

计算后栈中的数据

12

12

 

循环执行步骤1和步骤2,直到后缀表达式结束--------得到结果为19。

由此发现后缀表达式在运算过程中,解决了考虑优先级的关系----使计算变得更容易。

中缀表达式------后缀表达式:

怎么将中缀表达式转成后缀表达式?会使用到栈和队列。

首先用数组保存各个操作数和运算符。

数组中的各个数据

12

3

4

*

+

5

-

依次得到数组中的每一个元素,执行下列两个操作。

1.如果元素是操作数,就直接入队列。比如第一个数为12,入队列。

队列中的数据

12

2.如果元素是运算符,就要进行对栈进行判断

           1.如果栈是空栈,直接入栈。

栈中的数据

+

           2.如果栈不是空栈,使当前元素和栈顶的运算符进行判断,如果当前的运算符的优先级高于栈顶的优先级,就直接入栈。

                            比如当前元素是*,栈顶元素是+。

 

栈的原始数据

+          

-

比较优先级之后的数据

 *                           入栈

+

-

                       

依次和栈顶元素比较,直到出现当前元素优先级高于栈顶元素或栈为空,元素入栈。

                   比如当前运算是*,栈中的栈顶元素依次为* + -

栈中的原始数据

*      和 当前元素*比较           * 出栈,入队列。

+     和 当前元素*比较            当前元素* 入栈

-      

计算后的栈中数据

*      这个元素是当前元素入栈得到的

+

-

 

最后在队列中的数据就是后缀表达式了。

每一个人都有自己的理解,很有必有看一下数据结构这本书。

在数据结构这本书中的67页,有详细的过程,思路是一样的,可能更容易理解。

Java中的前缀表达式 java后缀表达式_Java中的前缀表达式

Java中的前缀表达式 java后缀表达式_入栈_02

实现代码 : 

                                      比较加减乘除运算符的优先级

// 判断运算符的优先级----其实可以使用带判断大小的枚举更好一些。
	public int precedence(String first,String next) {
		int number_1=0;
		int number_2=0;
		switch(first) {
		case "+":
			number_1=1;
			break;
		case "-":	
			number_1=1;
			break;
		case "*":
			number_1=2;
			break;
		case "/":
			number_1=2;
			break;
		}
		switch(next) {
		case "+":
			number_2=1;
			break;
		case "-":	
			number_2=1;
			break;
		case "*":
			number_2=2;
			break;
		case "/":
			number_2=2;
			break;
		}
		return number_1==number_2?0:number_1-number_2;
	}

                                             中缀表达式转后缀表达式

在这里我使用的是链表队列来保存中缀表达式的操作数和运算符。

/**
	 * 将中缀表达式转换成后缀表达式,返回的是一个后缀表达式的队列
	 * @param nifix   中缀表达式
	 * @return
	 */
	public LinkedList<String> toPostfix(LinkedList<String> nifix)  {
		Stack<String> opStack = new Stack<>();
		LinkedList<String> postfix = new LinkedList<>();
		Pattern pattern = Pattern.compile("\\+|-|\\*|/");
		for(String str: nifix)  {
			if(!pattern.matcher(str).matches()) {
				postfix.add(str);
			}
			else {
				if(opStack.isEmpty()) {
					opStack.push(str);
				}
				else {
					// 比较当前的 栈顶字符 和  str 的大小关系。
					while(!opStack.isEmpty()&&precedence(opStack.peek(),str)>=0) {
						postfix.add(opStack.pop());
					}
					opStack.push(str);
				}
			}
		}
		while(!opStack.isEmpty()) {
			postfix.add(opStack.pop());
		}
		return postfix;
	}

                                       实现加减乘除运算的方法   

/**
	 * 实现加减乘除运算
	 * 
	 * @param a   第一个操作数
	 * @param mark   运算符
	 * @param b   第二个操作数
	 * @return    result---运算结果
	 */
	public String computer(String a,String mark,String b)  {
		BigDecimal frist = new BigDecimal(a);
		BigDecimal next = new BigDecimal(b);
		switch(mark)  {
		case "+":
			result=String.valueOf(frist.add(next));
			break;
		case "-":	
			result=String.valueOf(frist.subtract(next));
			break;
		case "*":
			result=String.valueOf(frist.multiply(next));
			break;
		case "/":
			result=String.valueOf(frist.divide(next));
			break;
		}
		return result;
 	}

                                            后缀表达式的计算

// 用LinkedList列表实现队列的功能,计算后缀表达式的结果。
	public String postfixResult(LinkedList<String> postfix) {
		Stack<String> numberStack = new Stack<>();
		Pattern pattern = Pattern.compile("\\+|-|\\*|/");
		
		for(String str:postfix) {
			if(!pattern.matcher(str).matches()) {
				numberStack.push(str);
			}
			else {
				String next = numberStack.pop();
				String frist = numberStack.pop();
				result = computer(frist,str,next);
				numberStack.push(result);
			}
		}
		return numberStack.pop();
	}