1. 程式人生 > >關於Java寫逆波蘭表示式堆疊操作簡單實現

關於Java寫逆波蘭表示式堆疊操作簡單實現

目的:

重新熟悉逆波蘭表示式演算法,通過Java實現逆波蘭表示式從容更加深刻理解演算法與程式設計之間的關係;重新熟悉堆疊,並用Java程式實現堆疊的操作。

驗證方式:

圖書館查閱資料,手寫計算逆波蘭實現基本演算法,電腦Java程式設計實現演算法。

過程:

1. 通過讀書,重新拾起逆波蘭表示式演算法的記憶,中綴表示式轉化為字尾表示式,從而來實現計算器演算法。

2. 中綴表示式轉化為字尾表示式其實是運算表示式優先順序的體現。

例:中綴表示式:1.a+b*c 2.(a+b)*c 3.(a+b*c)/(d-e)

    字尾表示式:1.abc*+ 2.ab+c*3.abc*+de-/

由上例可以看出,優先順序決定字尾表示式的書寫。

3. 由具體演算法實現逆波蘭表示式:可建立兩個堆疊,一個用來放置運算子(Sign),一個用來放置依次安排的字尾表示式(RPN)。A.如果進來的是數值,直接壓到RPN中。B.如果進來的是‘(’,將它壓入Sign。C.如果進來的是運算子:1.檢視現在的Sign,如果它是‘(’,直接將運算子壓入Sign;2如果不是,則看進來的運算子比Sign現在的頂部元素運算子的優先順序是否更高,如果優先順序高,將運算子壓入Sign,如果不高於,則將Sign現在的頂部元素運算子取出壓入到RPN中。C.如果進來的是‘)’,則在Sign中查詢‘(’,並從Sign棧頂開始依次取出壓入到RPN,直到找到‘(’,並將‘(’刪除。

1. Java程式原始碼:

import java.util.Scanner;

public class shuzu_RPN {

        private char[]list;//放置最開始輸入的,被拆分之後的內容

        private char[]sign;//放置運算子

        private char[]rpnList;//放置逆波蘭表示式

        public staticvoidmain(String[] arge){

            shuzu_RPNrpn= newshuzu_RPN();

            //通過鍵盤輸入要要操作的中綴表示式

            rpn.getEquation();

            //將中綴表示式轉化為字尾表示式

            rpn.setRPN();

            //輸出表達式結果

            rpn.printResult();

        }

        //獲得整個算數表示式

        public voidgetEquation(){

            System.out.println("請輸入算數表示式:");

            //鍵盤輸入

            Scannersc= newScanner(System.in);

            Stringstr= sc.nextLine();

            //獲得輸入內容後,將字串內的空格都給消掉

            str.replaceAll(" ", "");

            //將輸入的字串轉換成字元放在list陣列中

            list = new char[str.length()];

            list = str.toCharArray();

            //輸出一遍

            System.out.println("您輸入的算數表示式是:");

            for(int i = 0; i<list.length; i++){

                System.out.print(list[i]);

            }

            System.out.println();

        }

        //讀取list,轉化為逆波蘭表示式

        public voidsetRPN(){

            //建立一個字元,用來指標作用

            char x;

            //將兩個字元陣列的長度限定

            sign = new char[list.length+1];

            rpnList = new char[list.length+1];

            //指符號陣列top

            sign[0] = '#';

            /*在下面的運算中,rpn沒加一個,rpnlen將指向下一位

signlen指向的是當前sign的最高位*/

            int signlen = 0;

            //rpn陣列top

            int rpnlen = 0;

            for(int i = 0; i < list.length; i++){

                //依次讀取字元,進行判斷

                x = list[i];

                switch(x){

                    case '(':

                        //符號位加1

                        signlen++;

                        sign[signlen] = x;

                        break;

                    case ')':

                        while(sign[signlen]!='('){

                            //依次將括號內容轉入到rpnList

                            rpnList[rpnlen] = sign[signlen];

                            //RPN加位

                            rpnlen++;

                            //運算子號位減位

                            signlen--;

                        }

                        //設定為空

                        signlen--;

                        break;

                    //接下來是算數運算子,加減乘除,當後一個優先順序不高於前一個優先順序,不出

                    case '+':

                    case '-':

                        for(int j = signlen; j >= 0; j--){

                            //+-的運算優先順序比*/的低

                            if(sign[j] == '('||signlen == 0){

                                break;

                            }else{

                                //直接將現在的棧頂元素搞到rpnList

                                rpnList[rpnlen] = sign[j];

                                signlen--;

                                rpnlen++;

                            }

                        }

                        signlen++;

                        sign[signlen] = x

                        break;

                    case '*':

                    case '/':

                        for(int j = signlen; j >= 0; j--){

                            //運算優先順序,*/的運算優先順序高於+-

                            if(sign[j] == '('||sign[j] == '+'||sign[j] == '-'||signlen == 0){

                                break;

                            }else{

                                //把現在的頂部運算子拿出來

                                rpnList[rpnlen] = sign[j];

                                signlen--;

                                rpnlen++;

                            }

                        }

                        signlen++;

                        sign[signlen] = x;             

                        break;

                    //遇到非運算子

                    default:       

                        rpnList[rpnlen] = x;

                        rpnlen++;

                }

            }

            //當符號陣列不為空,倒置放到rpn陣列

            while(signlen>0){

                rpnList[rpnlen] = sign[signlen];

                signlen--;

                rpnlen++;

            }

        }

        public voidprintResult(){

            System.out.println("生成的逆波蘭表示式:");

            for(int i = 0; i < rpnList.length; i++){

                System.out.print(rpnList[i]);

            }

        }

}

2. 運算結果:

請輸入算數表示式:

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

您輸入的算數表示式是:

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

生成的逆波蘭表示式:

21+31-*21-/_

結果:

經過查閱資料,仔細驗證,終於實現逆波蘭表示式,並實現後進先出的堆疊。演算法實現並不困難。最大的收穫是及時發現自己出現的眼高手低的毛病。及時補漏,並以此為戒,是這次試驗最大的收穫。

這是很久之前寫的一個簡單的實現文件,沒想到還留著.額...才疏學淺,請多多指教