1. 程式人生 > 其它 >逆波蘭表示式完整實現

逆波蘭表示式完整實現

  上篇中,我們只支援對整數實現,本篇完整實現,支援加減乘除和多位數、小數,思路與上篇相同。

因此直接上程式碼實現過程

package com.atxihua;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;

public class reversePolishMultiCalc {
    public static void main(String[] args) {
        String math
="12.8+(2 - 3.55)*4+10/5.0";//去除空格,故意在-前後新增空格進行測試 try { doCalc(doMatch(math)); } catch (Exception e) { e.printStackTrace(); } } /* * 匹配+ - * / ()運算子 * */ static final String SYMBOL="\\+|-|\\*|/|\\(|\\)"; static final String LEFT="(";
static final String RIGHT=")"; static final String ADD="+"; static final String MINUS="-"; static final String TIMES="*"; static final String DIVISON="/"; static final int LEVEL_01=1;//+ - static final int LEVEL_02=2;//* / static final int LEVEL_HIGH=Integer.MAX_VALUE;//括號 static
Stack<String> stack=new Stack<>(); static List<String> data= Collections.synchronizedList(new ArrayList<String>()); /* * 去除所有空白 * */ public static String replaceAllBlack(String s){ //\\s+匹配任何空白字元,包括空格、製表符、換頁符等待,等價於[\f\n\r\t\v] return s.replaceAll("\\s+","") ; } //判斷是不是數字 public static boolean isNumber(String s){ Pattern pattern=Pattern.compile("^[-\\+]?[.\\d]*$"); return pattern.matcher(s).matches(); } //判斷是不是運算子 public static boolean isSymbol(String s){ return s.matches(SYMBOL); } //匹配運算等級 public static int calcLevel(String s){ if("+".equals(s)||"-".equals(s)){ return LEVEL_01; }else if("*".equals(s)||"/".equals(s)){ return LEVEL_02; }else { return LEVEL_HIGH; } } public static List<String> doMatch(String s){ if(s==null||"".equals(s.trim()))throw new RuntimeException("data is empty"); //進行簡單校驗,保證第一個是數字 if(!isNumber(s.charAt(0)+""))throw new RuntimeException("data is illeagle,start not with a number"); s=replaceAllBlack(s); String each; int start=0; for(int i=0;i<s.length();i++){ if(isSymbol(s.charAt(i)+"")){ each=s.charAt(i)+""; //棧為空,(操作符,或者操作符優先順序大於棧頂優先順序&&操作符優先順序不是()優先順序及是 ) 不能直接入棧 if(stack.isEmpty()||LEFT.equals(each) ||((calcLevel(each)>calcLevel(stack.peek()))&&calcLevel(each)<LEVEL_HIGH)){ stack.push(each); }else if(!stack.isEmpty()&&calcLevel(each)<=calcLevel(stack.peek())){ //棧非空,操作符優先順序小於等於棧頂優先順序時出棧入列,直到棧為空,或者遇到(,最後操作符入棧 while (!stack.isEmpty()&& calcLevel(each)<=calcLevel(stack.peek())){ if(calcLevel(stack.peek())==LEVEL_HIGH){ break; } data.add(stack.pop()); } stack.push(each); }else if(RIGHT.equals(each)){ //)操作符,依次出棧入列直到空棧或者遇到第一個)操作符,此時)出棧 while (!stack.isEmpty()&&LEVEL_HIGH>=calcLevel(stack.peek())){ if(LEVEL_HIGH==calcLevel(stack.peek())){ stack.pop(); break; } data.add(stack.pop()); } } start=i; }else if(i==s.length()-1||isSymbol(s.charAt(i+1)+"")){ each=start==0?s.substring(start,i+1):s.substring(start+1,i+1); if(isNumber(each)){ data.add(each); continue; } throw new RuntimeException("data not match number"); } } //如果棧裡還有元素,此時元素需要依次出棧入列,可以想象棧裡剩下棧頂為/,棧底為+,應該依次出棧入列 //可以直接反轉整個stack新增到佇列中 Collections.reverse(stack); data.addAll(new ArrayList<>(stack)); System.out.println(data); return data; } //計算結果 public static Double doCalc(List<String> list){ Double d=0d; if(list==null||list.isEmpty()){ return null; } if(list.size()==1){ System.out.println(list); d=Double.valueOf(list.get(0)); return d; } ArrayList<String> list1=new ArrayList<>(); for(int i=0;i<list.size();i++){ list1.add(list.get(i)); if(isSymbol(list.get(i))){ Double d1=doTheMath(list.get(i-2),list.get(i-1),list.get(i)); list1.remove(i); list1.remove(i-1); list1.set(i-2,d1+""); list1.addAll(list.subList(i+1,list.size())); break; } } doCalc(list1); return d; } //運算 public static Double doTheMath(String s1, String s2, String symbol) { Double result; switch (symbol){ case ADD:result=Double.valueOf(s1)+Double.valueOf(s2);break; case MINUS:result=Double.valueOf(s1)-Double.valueOf(s2);break; case TIMES:result=Double.valueOf(s1)*Double.valueOf(s2);break; case DIVISON:result=Double.valueOf(s1)/Double.valueOf(s2);break; default:result=null; } return result; } }

執行結果: