1.3.10将算术表达式由中序表达式转为后序表达式(algs4)

前序表达式如何求值

对于一个前序表达式的求值而言,首先要从右至左扫描表达式,从右边第一个字符开始判断,如果当前字符是数字则一直到数字串的末尾再记录下来,如果是运算符,则将右边离得最近的两个“数字串”作相应的运算,以此作为一个新的“数字串”并记录下来。一直扫描到表达式的最左端时,最后运算的值也就是表达式的值。例如,前序表达式“- 1 + 2 3“的求值,扫描到3时,记录下这个数字串,扫描到2时,记录下这个数字串,当扫描到+时,将+右移做相邻两数字串的运算符,记为2+3,结果为5,记录下这个新数字串,并继续向左扫描,扫描到1时,记录下这个数字串,扫描到-时,将-右移做相邻两数字串的运算符,记为1-5,结果为-4,所以表达式的值为-4


中序表达式转换为前序表达式的一般算法

(1) 首先构造一个运算符栈(也可放置括号),运算符(以括号分界点)在栈内遵循越往栈顶优先级不降低的原则进行排列。

(2)从右至左扫描中序表达式,从右边第一个字符开始判断:

如果当前字符是数字,则分析到数字串的结尾并将数字串直接输出。

如果是运算符,则比较优先级。如果当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),则将运算符直接入栈;否则将栈顶运算符出栈并输出,直到当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),再将当前运算符入栈。

如果是括号,则根据括号的方向进行处理。如果是右括号,则直接入栈;否则,遇右括号前将所有的运算符全部出栈并输出,遇右括号后将左右的两括号一起删除。

(3) 重复上述操作(2)直至扫描结束,将栈内剩余运算符全部出栈并输出,再逆序输出字符串。中序表达式也就转换为前序表达式了。

将中序表达式“1+((2+3)*4)-5”转换为前序表达式。


中序表达式

前序表达式

(栈顶)运算符栈(栈尾)

说明

5

5

5,是数字串直接输出

-

5

-

-,栈内无运算符,直接入栈

5

-

),直接入栈

4

5 4

-

4,是数字串直接输出

*

5 4

-*

*,栈顶是括号,直接入栈

)

5 4

- ) * )

),直接入栈

3

5 4 3

- ) * )

3,是数字串直接输出

+

5 4 3

- ) * ) +

+,栈顶是括号,直接入栈

2

5 4 3 2

- ) * )+

2,是数字串直接输出

(

5 4 3 2+

- ) *

(,参考

(

5 4 3 2+*

-

(,参考

+

5 4 3 2+*

-+

+,优先级大于等于栈顶运算符,直接入栈

1

5 4 3 2+*1

-+

1,是数字串直接输出

5 4 3 2+*1+-

扫描结束,将栈内剩余运算符全部出栈并输出

- + 1 * + 2 3 4 5

逆序输出字符串

 


后序表达式如何求值

从左到右扫描表达式,计算方法同前序表达式


中序表达式转换为后序表达式的一般算法

1、当输入的是操作数时候,直接输出

2、当输入开括号时候,把它压栈

3、当输入的是闭括号时候,先判断栈是否为空,若为空,则发生错误并进行相关处理。若非空,把栈中元素依次出栈输出,直到遇到第一个开括号,若没有遇到开括号,也发生错误,进行相关处理

4、当输入是运算符op+-×/)时候

a)循环,当(栈非空and栈顶不是开括号and栈顶运算符的优先级不低于输入的运算符的优先级)时,反复操作:将栈顶元素出栈输出

b)把输入的运算符op压栈

5、当中序表达式的符号序列全部读入后,若栈内仍有元素,把他们依次出栈输出。若弹出的元素遇到空括号,则说明不匹配,发生错误,并进行相关处理

 

例如(a+b)*(c+d)这个式子,依演算法的输出过程如下:

OP  

STACK   

OUTPUT  

(

(

-

a

(

a

+

(+

a

b

(+

ab

)

-

ab+

*

*

ab+

(

*(

ab+

c

*(

ab+c

+

*(+

ab+c

d

*(+

ab+cd

)

*

ab+cd+

-

-

ab+cd+*   


转化算法区别:

将中序式转为前序式,则在读取中序式时是由后往前读取,而左右括号的处理方式相反,其余不变,但输出之前必须先置入堆叠,待转换完成后再将堆叠中的值由上往下读出,如此就是前序表示式。


中序表达式

            2*3/(2-1)+3*(4-1)          

前序表达式

(前缀表达式、波兰式)

  +/*23-21*3-41

后序表达式

       (后缀表达式、逆波兰式)      

    23*21-/341-*+

2321-/341-*+*



package _1_3linkedList;
import edu.princeton.cs.algs4.Stack;
import java.util.Scanner;

/*1.3.10将算术表达式由中序表达式转为后序表达式
*/
public class InfixToPostfix
{

	public static void main(String[] args)
	{
		Stack<Character> operatorStack=new Stack<Character>();  /*类型与下面的数组元素相对应*/
		Scanner sc=new Scanner(System.in);
		String s=sc.nextLine();
		char c[]=s.toCharArray();     /*对字符串进行分割或转换为字符数组*/
		/*从前往后扫描*/
		for(int i=0;i<c.length;i++)
		{
			if(c[i]=='(')/*当输入左括号时候,把它压栈*/
				operatorStack.push(c[i]);
			else if(c[i]=='+'||c[i]=='-'||c[i]=='*'||c[i]=='/')
			{	/*当输入是运算符op(+、- 、×、/)时候
				 * a)循环,当(栈非空and栈顶不是左括号and栈顶运算符的优先级不低于输入的运算符的优先级)时,
				 * 反复操作:将栈顶元素出栈输出
				 * b)把输入的运算符op压栈
				 * */
				boolean isEmpty;
				boolean isLeftParen;
				boolean isLowerOperator=false;
				isEmpty=operatorStack.isEmpty();
				if(!isEmpty)
				{
					char cTop=operatorStack.peek();
					isLeftParen=(cTop=='(');
					if(cTop=='+'||cTop=='-'&&c[i]=='*'||c[i]=='/')
						isLowerOperator=true;
					if(!(isEmpty||isLeftParen||isLowerOperator))
					{

						for(int j=0;j<operatorStack.size();j++)
							System.out.print(operatorStack.pop());
					}
				}
				operatorStack.push(c[i]);
			}else if(c[i]==')')
			{	/*当输入的是右括号时候,先判断栈是否为空,若为空,则发生错误并进行相关处理。
				 * 若非空,把栈中元素依次出栈输出,直到遇到第一个左括号,若没有遇到左括号,也发生错误,进行相关处理*/
				char pop=operatorStack.pop();
				while(pop!='(')
				{
					System.out.print(pop);
					pop=operatorStack.pop();
				}
			}else
				System.out.print(c[i]);
			
		}
		/* 当中序表达式的符号序列全部读入后,若栈内仍有元素,把他们依次出栈输出 */
		for(char ch:operatorStack)
			System.out.print(ch);
	}

}

2*3/(2-1)+3*(4-1) 
2321-/341- *+*


简单版本:

package _1_3linkedList;

import java.util.Scanner;
/*1.3.10将算术表达式由中序表达式转为后序表达式(未省略括号,以括号代替优先级)
 * 需要一个操作符栈存储操作符
 * */

public class InfixToPostfix {
	public static void main(String[] args) 
	{
		Stack<Character> operatorStack = new Stack<Character>();       /*类型与下面的数组元素相对应*/
		Scanner sc=new Scanner(System.in);
		String s=sc.nextLine();
		char c[]=s.toCharArray();                                   /*对字符串进行分割或转换为字符数组*/
		for(int i=0;i<c.length;i++) 
		{
			switch (c[i])
			{/*将未省略括号的中序表达式转换为后序表达式
			1.遇到左括号时忽略
			2.遇到操作符入栈
			3.遇到右括号时弹出操作符
			4.遇到操作数时直接输出
			*/
				case '(':                                         
					break;
				case '+':
				case '-':
				case '*':
				case '/':
					operatorStack.push(c[i]);
					break;
				case ')':
					System.out.print(operatorStack.pop());        
					break;
				default:
					System.out.print(c[i]);                      
			}
		}
		
	}
}

(3+(((1+2)/3)*(4+5)))
312+3/45+*+


相关阅读:

“中序表达式”转换为“前序表达式”、“后序表达式”

中序、前序、后序表达式



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值