棧實(shí)現(xiàn)四則運(yùn)算--中綴表達(dá)式如何轉(zhuǎn)換成后綴表達(dá)式顾彰?

中綴表達(dá)式怎么轉(zhuǎn)成后綴表達(dá)式塘偎?

  • 1)初始化兩個(gè)棧,分別用于存儲(chǔ)后綴表達(dá)式結(jié)果S2和利用S1棧完成運(yùn)算符號(hào)的指定位置輸出易稠;
  • 2)從左往右掃描中綴表達(dá)式缸废,當(dāng)掃描到數(shù)字時(shí),直接壓入到S2棧中驶社;
  • 3)當(dāng)掃描到運(yùn)算符號(hào)時(shí)(不包括括號(hào)):
  • case1: 如果S1棧為空或者棧頂符號(hào)為“(”時(shí)企量,直接將掃描的運(yùn)算符號(hào)壓入到棧S1中;
  • case2: 如果不是case1情況亡电,比較掃描到的符號(hào)與S1棧頂符號(hào)的優(yōu)先級(jí)届巩,如果優(yōu)先級(jí)高于棧頂符號(hào),則直接壓入棧S1逊抡;否則姆泻,彈出S1棧頂符號(hào)并壓入S2棧中零酪,返回地 3)繼續(xù)與S1棧頂符號(hào)比較冒嫡;
  • 4)當(dāng)掃描到括號(hào)時(shí)(包括左右括號(hào)):
  • case1:如果是左括號(hào)“(”,則直接壓入棧S1中四苇;
  • case2:如果是右括號(hào)“)”孝凌,則依次彈出棧S1棧頂符號(hào)并壓入S2棧中,直至S1棧頂元素為左括號(hào)“(”月腋,彈出棧頂符號(hào)(即左括號(hào))丟棄蟀架;
  • 5)重復(fù)2)3)4)步驟瓣赂,直至掃描到中綴表達(dá)式最后一位,將棧S1中所有符號(hào)彈出并依次壓入到S2棧中片拍;
  • 6)依次彈出S2棧中元素輸出煌集,后綴表達(dá)結(jié)果為輸出結(jié)果逆序。

具體代碼實(shí)現(xiàn)如下:

import java.util.*;

public class PolandNotation {
    public static void main(String[] args) {
        //驗(yàn)證:給定后綴表達(dá)式完成四則運(yùn)算
        //輸入后綴表達(dá)式,每個(gè)數(shù)字和符號(hào)中間用空格隔開
        String suffixExpression ="1 2.0 3 * - 5.8 3 * 11 - 2 * 1 - +";//(1-2*3)+((5.8*3-11)*2-1)
        // 將后綴表達(dá)式字符串存入到列表中
        List<String> sufeList1 = getList(suffixExpression);
        System.out.println("后綴表達(dá)式="+sufeList1);
        //根據(jù)已知的后綴表達(dá)式計(jì)算結(jié)果
        float res1 = calculate(sufeList1);
        System.out.println("計(jì)算結(jié)果="+ res1);
        
        //驗(yàn)證:給定中綴表達(dá)式完成四則運(yùn)算
        //給定中綴表達(dá)式捌省,將其字符串存入到列表中
        String infixExpression= "(1-2.0*3)+((5.8*3-11)*2-1)";
        List<String> infeList = infixExpressionToList(infixExpression);
        System.out.println("中綴表達(dá)式="+infeList);
        //將中綴表達(dá)式轉(zhuǎn)換成后綴表達(dá)式并存入列表
        List<String> sufeList2 = infixTosuffix(infeList);
        System.out.println("后綴表達(dá)式="+sufeList2);
      //根據(jù)轉(zhuǎn)換的后綴表達(dá)式計(jì)算結(jié)果
        float res2 = calculate(sufeList2);
        System.out.println("計(jì)算結(jié)果="+ res2);
    }
    
    
    /**
     * 將中綴表達(dá)式存儲(chǔ)到列表中苫纤,便于后面轉(zhuǎn)換成后綴表達(dá)式處理
     * @param s 中綴表達(dá)式字符串
     * @return 存儲(chǔ)分割后的中綴表達(dá)式的列表
     */
    public static List<String> infixExpressionToList(String s){
        List<String> infelist = new ArrayList<>();
        int index = 0;
        String ss;
        char c;
        do {
            if((c=s.charAt(index))!='.' && !Character.isDigit(c=s.charAt(index))) {//判斷是否為數(shù)字或小數(shù)點(diǎn)
                //如果不是,那么就是運(yùn)算符號(hào)或者括號(hào),轉(zhuǎn)成字符轉(zhuǎn)字符串并直接放入列表
                infelist.add(c+"");
                index++;
            }else {//如果是數(shù)字或小數(shù)點(diǎn)纲缓,需要拼接成完整數(shù)
                ss = "";
                //注意需要判斷index是否指向超出字符串長(zhǎng)度
                while(index<s.length() && (Character.isDigit(c=s.charAt(index)) || (c=s.charAt(index))=='.')) {
                    ss += c;
                    index++;
                }
                infelist.add(ss);   
            }
        }while(index < s.length());
        return infelist;
    }

        
    /**
     * 將中綴表達(dá)式轉(zhuǎn)換成后綴表達(dá)式
     * 存在問題:負(fù)數(shù)不能直接參與計(jì)算(eg:-5),需要加0(eg:0-5) >>> 需要改進(jìn)的地方
     * @param ls 中綴表達(dá)式列表
     * @return 后綴表達(dá)式列表
     */
    public static List<String> infixTosuffix(List<String> infixls){
        Stack<String> s1 = new Stack<>();
        Stack<String> s2 = new Stack<>();
        List<String> suffixls = new ArrayList<>();
        
        for(String item:infixls) {
            if(item.matches("^[+-]?\\d+(\\.\\d+)?$")) {//如果是數(shù)字卷拘,直接壓入棧s1
                s2.push(item);
            }else if(item.equals("(")) {//如果是左括號(hào),直接壓入棧s1
                s1.push(item);
            }else if(item.equals(")")) {//如果是右括號(hào)祝高,彈出棧s1元素直到遇到第一個(gè)“(”停止栗弟,并將彈出元素壓入棧s2
                while(!(s1.peek()).equals("(")) {//如果沒遇到左括號(hào),彈出s1然后壓入s2
                    s2.push(s1.pop());
                }
                s1.pop();//彈出左括號(hào)丟棄
            }else{//如果是運(yùn)算符號(hào)
                if(s1.isEmpty() || (s1.peek()).equals("(")) {//case1:s1站空或棧頂元素為左括號(hào),直接壓入棧s1
                    s1.push(item);  
                }else {//case2:需要比較優(yōu)先級(jí)
                    if(priority(item) > priority(s1.peek())) {//如果掃描的運(yùn)算符優(yōu)先級(jí)高于棧頂元素工闺,直接壓入棧s1
                        s1.push(item);
                    }else {
                        s2.push(s1.pop());//彈出棧s1棧頂元素壓入棧s2
                        //當(dāng)非空非左括號(hào)且掃描運(yùn)算發(fā)優(yōu)先級(jí)不大于棧頂符號(hào)乍赫,繼續(xù)判斷優(yōu)先級(jí)
                        while(!s1.isEmpty() && !(s1.peek()).equals("(") && priority(item) <= priority(s1.peek())) {
                            s2.push(s1.pop());  
                            }
                        s1.push(item);
                        }
                    }
            }
        }
        while(!s1.isEmpty()) {//將棧s1依次彈出剩余元素壓入棧s2
            s2.push(s1.pop());
        }
        //彈出棧2元素存入列表中并反轉(zhuǎn)列表返回
        while(!s2.isEmpty()) {
            suffixls.add(s2.pop());
        }
        Collections.reverse(suffixls);
        return suffixls;
    }
    
    
    /**
     * 將后綴表達(dá)式字符串分割后存儲(chǔ)在列表中
     * @param suffixExpression 后綴表達(dá)式字符串
     * @return 存儲(chǔ)后綴表達(dá)式的列表
     */
    public static List<String> getList(String suffixExpression){
        String[] split = suffixExpression.split(" ");
        List<String> list = new ArrayList<String>();
        for(String s:split){
            list.add(s);
        }
        return list;
    }
     
    
    /**
     * 判斷運(yùn)算符號(hào)優(yōu)先級(jí),返回值越大優(yōu)先級(jí)越高
     * @param oper 運(yùn)算符號(hào)字符串格式
     * @return 1陆蟆,0耿焊,-1值越大優(yōu)先級(jí)越高
     */
    public static int priority(String oper) {
        if(oper.equals("*") || oper.equals("/")) {
            return 1;
        }else if(oper.equals("+") || oper.equals("-")) {
            return 0;
        }else {
            return -1;
        }
    }
    
    
    /**
     * 完成四則運(yùn)算
     * @param list 存儲(chǔ)后綴表達(dá)式的列表
     * @return 計(jì)算結(jié)果
     */
    public static float calculate(List<String> list) {
        Stack<String> stack = new Stack<>();
        for(String item:list) {
            //用正則表達(dá)式匹配,此處可匹配正負(fù)數(shù)和小數(shù)
            if(item.matches("^[+-]?\\d+(\\.\\d+)?$")) {
                stack.push(item);
            }else {
                float num1 = Float.parseFloat(stack.pop());
                float num2 = Float.parseFloat(stack.pop());
                float res = 0;
                if(item.equals("+")) {
                    res = num1 + num2;
                }else if(item.equals("-")) {
                    res = num2 - num1;
                }else if(item.equals("*")) {
                    res = num1 * num2;
                }else if(item.equals("/")){
                    res = num2 / num1;
                }else {
                    throw new RuntimeException("運(yùn)算符號(hào)不對(duì)勁啊");
                }
                stack.push(String.valueOf(res));    
            }
        }
        return Float.parseFloat(stack.pop());   
    }   
}

Quiet and Quick, Salute!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末遍搞,一起剝皮案震驚了整個(gè)濱河市罗侯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌溪猿,老刑警劉巖钩杰,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異诊县,居然都是意外死亡讲弄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門依痊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來避除,“玉大人,你說我怎么就攤上這事胸嘁∑堪冢” “怎么了?”我有些...
    開封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵性宏,是天一觀的道長(zhǎng)群井。 經(jīng)常有香客問我,道長(zhǎng)毫胜,這世上最難降的妖魔是什么书斜? 我笑而不...
    開封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任诬辈,我火速辦了婚禮,結(jié)果婚禮上荐吉,老公的妹妹穿的比我還像新娘焙糟。我一直安慰自己,他們只是感情好样屠,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開白布酬荞。 她就那樣靜靜地躺著,像睡著了一般瞧哟。 火紅的嫁衣襯著肌膚如雪混巧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天勤揩,我揣著相機(jī)與錄音咧党,去河邊找鬼。 笑死陨亡,一個(gè)胖子當(dāng)著我的面吹牛傍衡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播负蠕,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼蛙埂,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了遮糖?” 一聲冷哼從身側(cè)響起绣的,我...
    開封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎欲账,沒想到半個(gè)月后屡江,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赛不,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年惩嘉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片踢故。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡文黎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出殿较,到底是詐尸還是另有隱情耸峭,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布斜脂,位于F島的核電站抓艳,受9級(jí)特大地震影響触机,放射性物質(zhì)發(fā)生泄漏帚戳。R本人自食惡果不足惜玷或,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望片任。 院中可真熱鬧偏友,春花似錦、人聲如沸对供。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)产场。三九已至鹅髓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間京景,已是汗流浹背窿冯。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留确徙,地道東北人醒串。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鄙皇,于是被迫代替她去往敵國(guó)和親芜赌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容