数据结构与算法(Java描述)-8、中缀表达式转换后缀表达式算法

一、表达式的三种形式

中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3
后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:2 1 + 3 *
前缀表达式:同后缀表达式一样,不包含括号,运算符放在两个运算对象的前面,如:* + 2 1 3 

二、表达式的转换

将中缀表达式转换为后缀表达式:

(1)当读到数字直接送至输出队列中;
(2)当读到运算符t时:
    a.将栈中所有优先级高于或等于t的运算符弹出,送到输出队列中;
  这句话不好理解,可以说成这样,从栈顶开始,依次弹出比当前处理的运算符优先级高的运算符,直到一个比它优先级低的或者遇到了一个左括号就停止。
    b.t进栈; 
(3)读到左括号时总是将它压入栈中; 
(4)读到右括号时,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号; 
(5)中缀表达式全部读完后,若栈中仍有运算符,将其送到输出队列中。

中缀表达式:3+(2-5)*6/3 转换为后缀表达式的过程:
后缀表达式              栈

3                              +
3                         +(
32                       +(
32                       +(-
325                       +(-
325-                   +
325-                     +*
325-6                   +*
325-6*                     +/
325-6*3                   +/
325-6*3/+
最终后缀表达式为:325-6*3/+

运用后缀表达式进行计算:
 (1)建立一个栈stack; 
 (2)从左到右读后缀表达式,读到数字就将它转换为数值压入栈stack中,读到运算符则从栈中依次弹出两个数分别到b和a,然后以“a 运算符 b”的形式计算机出结果,再压加栈stack中;
 (3)如果后缀表达式未读完,就重复上面过程,最后输出栈顶的数值则为结束。

3+(2-5)*6/3=-3 ,其后缀表达式为:325-6*3/+
运算过程如下:
栈             运算
3 2 5                          325入栈
3               2-5=-3
3 -3                           运算结果进栈
3 -3 6
3               -3*6=-18 
3 -18 3         -18/3=-6      
3 -6            3+(-6)=-3  
-3

三、算法实现

/**
 * 将中缀表达式转换为后缀表达式:
(1)当读到数字直接送至输出队列中;
(2)当读到运算符t时:
    a.将栈中所有优先级高于或等于t的运算符弹出,送到输出队列中;
  这句话不好理解,可以说成这样,从栈顶开始,依次弹出比当前处理的运算符优先级高的运算符,直到一个比它优先级低的或者遇到了一个左括号就停止。
    b.t进栈; 
(3)读到左括号时总是将它压入栈中; 
(4)读到右括号时,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号; 
(5)中缀表达式全部读完后,若栈中仍有运算符,将其送到输出队列中。
 */
import java.util.Stack;
import java.util.regex.Pattern;
public class StringToArithmetic {

	//将中缀表达式转化成后缀表达式
	public static String infixToSuffix(String exp) {
		//创建操作数栈
		Stack<Character> stack=new Stack<Character>();
		//转换后的后缀字符串序列
		String suffix="";
		
		int len=exp.length();
		for (int i = 0; i < len; i++) {
			char ch=exp.charAt(i);
			//临时字符变量
			char temp;
			//忽略空格
			switch (ch) {
			case ' ':
				break;
			//如果是左括号直接加入栈中
			case '(':
				stack.push(ch);
				break;
			
			//如果是+ - 那么则弹出所有字符至序列中,直到遇到左括号为止,然后再把该运算符压到堆栈中
			case '+':
			case '-':
				while(!stack.isEmpty()) {
					temp=stack.pop();
					if(temp=='(') {
						stack.push(temp);
						break;
					}
					suffix+=temp;
				}
				stack.push(ch);
				break;
				
			//如果是* /,则弹出所有字符至序列中,直到遇到左括号、+、-号为止,然后把该运算符压到堆栈中
			case '*':
			case '/':
				while(!stack.isEmpty()) {
					temp=stack.pop();
					if(temp=='('||temp=='+'||temp=='-') {
						stack.push(temp);
						break;
					}
					suffix+=temp;
				}
				stack.push(ch);
				break;
				
			//如果是* /,则弹出所有字符至序列中,直到遇到左括号、+、-号为止,然后把该运算符压到堆栈中
			case ')':
				while(!stack.isEmpty()) {
					temp=stack.pop();
					if(temp=='(') {
						break;
					}
					suffix+=temp;
				}
				break;
			//默认,如果是数字,直接加到输出队列中
			default:
				suffix+=ch;
				break;
			}
		}
		//如果堆栈不为空,依次把所有的字符加入序列中
		while(!stack.isEmpty()) {
			suffix+=stack.pop();
		}
		return suffix;
	}
	
	//输入后缀表达式得到计算结果
	public static double suffixToArithmetic(String exp) {
		Stack<Double> stack=new Stack<Double>();
		//使用正则表达式匹配数字
		Pattern pattern=Pattern.compile("\\d+||(\\d+\\.\\d+)");
		//将字符串分割成字符串数组
		String strs[]=exp.split("");
		for (int i = 0; i < strs.length; i++) {
			if(strs[i].equals(""))
				continue;
			//如果是数字,则入栈
			if((pattern.matcher(strs[i])).matches()) {
				stack.push(Double.parseDouble(strs[i]));
			}else {
				//如果是运算符,则弹出运算符,计算结果
				double b=stack.pop();
				double a=stack.pop();
				//将运算结果重新压入栈中
				stack.push(calcute(a, b, strs[i]));
			}
		}
		return stack.pop();
	}
	
	//根据符号计算最终结果
	public static double calcute(double a,double b,String simble) {
		if(simble.trim().equals("+"))
			return a+b;
		if(simble.trim().equals("-"))
			return a-b;
		if(simble.trim().equals("*"))
			return a*b;
		if(simble.trim().equals("/"))
			return a/b;
		return 0;
	}
	
	
	public static void main(String[] args) {
		String exp="3+(2-5)*6/3";
		String re=infixToSuffix(exp);//325-6*3/+ 
		double result=suffixToArithmetic(re);
		System.out.println(result);//-3.0
	}
}


猜你喜欢

转载自blog.csdn.net/m0_37897502/article/details/78313942