1. 程式人生 > >java 計算中綴表示式結果

java 計算中綴表示式結果

思路:
  把輸入的中綴表示式轉成字尾表示式,利用正則表示式來處理數字,然後利用棧來得出結果。
流程
中綴表示式轉字尾表示式的方法:
1.遇到運算元:直接輸出(新增到字尾表示式中)
2.棧為空時,遇到運算子,直接入棧
3.遇到左括號:將其入棧
4.遇到右括號:執行出棧操作,並將出棧的元素輸出,直到彈出棧的是左括號,左括號不輸出。
5.遇到其他運算子:加減乘除:彈出所有優先順序大於或者等於該運算子的棧頂元素,然後將該運算子入棧
6.最終將棧中的元素依次出棧,輸出。
例如
a+b*c+(d*e+f)*g ----> abc*+de*f+g*+
遇到a:直接輸出:
字尾表示式:a
堆疊:空
遇到+:堆疊:空,所以+入棧
字尾表示式:a
堆疊:+
遇到b: 直接輸出
字尾表示式:ab
堆疊:+
遇到*:堆疊非空,但是+的優先順序不高於*,所以*入棧
字尾表示式: ab
堆疊:*+
遇到c:直接輸出
字尾表示式:abc
堆疊:*+
遇到+:堆疊非空,堆疊中的*優先順序大於+,輸出並出棧,堆疊中的+優先順序等於+,輸出並出棧,然後再將該運算子(+)入棧
字尾表示式:abc*+
堆疊:+
遇到(:直接入棧
字尾表示式:abc*+
堆疊:(+
遇到d:輸出
字尾表示式:abc*+d
堆疊:(+
遇到*:堆疊非空,堆疊中的(優先順序小於*,所以不出棧
字尾表示式:abc*+d
堆疊:*(+
遇到e:輸出
字尾表示式:abc*+de
堆疊:*(+
遇到+:由於*的優先順序大於+,輸出並出棧,但是(的優先順序低於+,所以將*出棧,+入棧
字尾表示式:abc*+de*
堆疊:+(+
遇到f:輸出
字尾表示式:abc*+de*f
堆疊:+(+
遇到):執行出棧並輸出元素,直到彈出左括號,所括號不輸出
字尾表示式:abc*+de*f+
堆疊:+
遇到*:堆疊為空,入棧
字尾表示式: abc*+de*f+
堆疊:*+
遇到g:輸出
字尾表示式:abc*+de*f+g
堆疊:*+
遇到中綴表示式結束:彈出所有的運算子並輸出
字尾表示式:abc*+de*f+g*+
堆疊:空

程式碼:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class midToBack {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in=new Scanner(System.in);
		 
        while(in.hasNextLine()){
        	String s = in.nextLine();
        
		try {
			List<Object> list = trans(s);
			
			Stack<Double>  result=new Stack<Double>();
			double res=f(list,result);
			System.out.println(res);
		} catch (Exception e) {
			// TODO Auto-generated catch block
		System.out.println("表示式不合法!");
		}
        }
	}

	private static double f(List<Object> list, Stack<Double> result) {
		// TODO Auto-generated method stub
		Iterator it=list.iterator();
        while(it.hasNext()){
        	String m=it.next().toString();
        	if (m.equals("+")||m.equals("-")||m.equals("*")||m.equals("/")) {
        		double b=result.pop();
				
				double a=result.pop();
				double v=g(a,b,m);
				result.push(v);
			}else {
				result.push(Double.valueOf(m));
			}
        }
		return(result.pop());
	}

	private static double g(double a, double b, String m) {
		// TODO Auto-generated method stub

		double v=0;
        switch (m)
        {
        case "+":
            v=a+b;
            break;
        case "-":
            v=a-b;
            break;
        case "*":
            v=a*b;
            break;
        case "/":
            v=a/b;
            break;
        }
        return v;
    
	}

	private static List<Object> trans(String s) {
		// TODO Auto-generated method stub
		Stack<Character> op=new Stack<Character>();
		
		
		ArrayList<Object> list=new ArrayList<Object>();
		Pattern P=Pattern.compile("[0-9]+(\\.[0-9]+)?");   //正則表示式來處理帶小數點的數字
        int i=0;
        
        while(i<s.length()){
        	char c=s.charAt(i);
        	if (c>='0'&&c<='9') {
				String s1=s.substring(i);
				Matcher m =P.matcher(s1);
				if (m.find()) {    //取匹配到的第一個數字
					s1=m.group();
					
					list.add(s1);
				}
				i=i+s1.length();
				continue;
			}else if (c=='(') {
				op.push(c);
			}else if (c==')') {
				char p=op.pop();
				while(p!='('){
					list.add(p);
					p=op.pop();
				}
			}else if (c=='+'||c=='-') {
				while(!op.isEmpty()&&(op.peek()=='+'||op.peek()=='-'||
						op.peek()=='*'||op.peek()=='/')){
					
					list.add(op.pop());
				}
				op.push(c);
			}else if (c=='*'||c=='/') {
				while(!op.isEmpty()&&(op.peek()=='*'||op.peek()=='/')){
					list.add(op.pop());
				}
				op.push(c);
			}
        	i++;
        }
		
		while(!op.isEmpty()){
			list.add(op.pop());
		}
		return list;
	}

}

測試: