Java數據結構和算法(六)——前綴、中綴、後綴表達式

前面咱們介紹了三種數據結構,第一種數組主要用做數據存儲,可是後面的兩種棧和隊列咱們說主要做爲程序功能實現的輔助工具,其中在介紹棧時咱們知道棧能夠用來作單詞逆序,匹配關鍵字符等等,那它還有別的什麼功能嗎?以及數據結構與本篇博客的主題前綴、中綴、後綴表達式有什麼關係呢?數組

一、人如何解析算術表達式

  如何解析算術表達式?或者換種說法,遇到某個算術表達式,咱們是如何計算的:數據結構

  ①、求值 3+4-5工具

  

  這個表達式,咱們在看到3+4後都不能直接計算3+4的值,知道看到4後面的 - 號,由於減號的優先級和前面的加號同樣,因此能夠計算3+4的值了,若是4後面是 * 或者 /,那麼就要在乘除事後才能作加法操做,好比:測試

  ②、求值 3+4*5this

  

 

  這個不能先求3+4的值,由於4後面的*運算級別比前面的+高。經過這兩個表達式的說明,咱們能夠總結解析表達式的時候遵循的幾條規則:spa

  ①、從左到右讀取算式。.net

  ②、已經讀到了能夠計算值的兩個操做數和一個操做符時,能夠計算,並用計算結果代替那兩個操做數和一個操做符。設計

  ③、繼續這個過程,從左到右,能算就算,直到表達式的結尾。code

二、計算機如何解析算術表達式

  對於前面的表達式 3+4-5,咱們人是有思惟能力的,能根據操做符的位置,以及操做符的優先級別能算出該表達式的結果。可是計算機怎麼算?對象

  計算機必需要向前(從左到右)來讀取操做數和操做符,等到讀取足夠的信息來執行一個運算時,找到兩個操做數和一個操做符進行運算,有時候若是後面是更高級別的操做符或者括號時,就必須推遲運算,必需要解析到後面級別高的運算,而後回頭來執行前面的運算。咱們發現這個過程是極其繁瑣的,而計算機是一個機器,只認識高低電平,想要完成一個簡單表達式的計算,咱們可能要設計出很複雜的邏輯電路來控制計算過程,那更不用說很複雜的算術表達式,因此這樣來解析算術表達式是不合理的,那麼咱們應該採起什麼辦法呢?

  請你們先看看什麼是前綴表達式,中綴表達式,後綴表達式:這三種表達式其實就是算術表達式的三種寫法,以 3+4-5爲例

  ①、前綴表達式:操做符在操做數的前面,好比 +-543

  ②、中綴表達式:操做符在操做數的中間,這也是人類最容易識別的算術表達式 3+4-5

  ③、後綴表達式:操做符在操做數的後面,好比 34+5-

  上面咱們講的人是如何解析算術表達式的,也就是解析中綴表達式,這是人最容易識別的,可是計算機不容易識別,計算機容易識別的是前綴表達式和後綴表達式,將中綴表達式轉換爲前綴表達式或者後綴表達式以後,計算機能很快計算出表達式的值,那麼中綴表達式是如何轉換爲前綴表達式和後綴表達式,以及計算機是如何解析前綴表達式和後綴表達式來獲得結果的呢?

三、後綴表達式

  後綴表達式,指的是不包含括號,運算符放在兩個運算對象的後面,全部的計算按運算符出現的順序,嚴格從左向右進行(再也不考慮運算符的優先規則)。

  因爲後綴表達式的運算符在兩個操做數的後面,那麼計算機在解析後綴表達式的時候,只須要從左向右掃描,也就是隻須要向前掃描,而不用回頭掃描,遇到運算符就將運算符放在前面兩個操做符的中間(這裏先不考慮乘方相似的單目運算),一直運算到最右邊的運算符,那麼就得出運算結果了。既而後綴表達式這麼好,那麼問題來了:

  ①、如何將中綴表達式轉換爲後綴表達式?

  對於這個問題,轉換的規則以下:

  

  1、先自定義一個棧

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

package com.ys.poland;

 

public class MyCharStack {

    private char[] array;

    private int maxSize;

    private int top;

     

    public MyCharStack(int size){

        this.maxSize = size;

        array = new char[size];

        top = -1;

    }

     

    //壓入數據

    public void push(char value){

        if(top < maxSize-1){

            array[++top] = value;

        }

    }

     

    //彈出棧頂數據

    public char pop(){

        return array[top--];

    }

     

    //訪問棧頂數據

    public char peek(){

        return array[top];

    }

     

    //查看指定位置的元素

    public char peekN(int n){

        return array[n];

    }

     

    //爲了便於後面分解展現棧中的內容,咱們增長了一個遍歷棧的方法(實際上棧只能訪問棧頂元素的)

    public void displayStack(){

        System.out.print("Stack(bottom-->top):");

        for(int i = 0 ; i < top+1; i++){

            System.out.print(peekN(i));

            System.out.print(' ');

        }

        System.out.println("");

    }

     

    //判斷棧是否爲空

    public boolean isEmpty(){

        return (top == -1);

    }

     

    //判斷棧是否滿了

    public boolean isFull(){

        return (top == maxSize-1);

    }

 

}

  2、前綴表達式轉換爲後綴表達式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

package com.ys.poland;

 

public class InfixToSuffix {

    private MyCharStack s1;//定義運算符棧

    private MyCharStack s2;//定義存儲結果棧

    private String input;

     

    //默認構造方法,參數爲輸入的中綴表達式

    public InfixToSuffix(String in){

        input = in;

        s1 = new MyCharStack(input.length());

        s2 = new MyCharStack(input.length());

    }

    //中綴表達式轉換爲後綴表達式,將結果存儲在棧中返回,逆序顯示即後綴表達式

    public MyCharStack doTrans(){

        for(int j = 0 ; j < input.length() ; j++){

            System.out.print("s1棧元素爲:");

            s1.displayStack();

            System.out.print("s2棧元素爲:");

            s2.displayStack();

            char ch = input.charAt(j);

            System.out.println("當前解析的字符:"+ch);

            switch (ch) {

            case '+':

            case '-':

                gotOper(ch,1);

                break;

            case '*':

            case '/':

                gotOper(ch,2);

                break;

            case '(':

                s1.push(ch);//若是當前字符是'(',則將其入棧

                break;

            case ')':

                gotParen(ch);

                break;

            default:

                //一、若是當前解析的字符是操做數,則直接壓入s2

                //二、

                s2.push(ch);

                break;

            }//end switch

        }//end for

         

        while(!s1.isEmpty()){

            s2.push(s1.pop());

        }

        return s2;

    }

     

    public void gotOper(char opThis,int prec1){

        while(!s1.isEmpty()){

            char opTop = s1.pop();

            if(opTop == '('){//若是棧頂是'(',直接將操做符壓入s1

                s1.push(opTop);

                break;

            }else{

                int prec2;

                if(opTop == '+' || opTop == '-'){

                    prec2 = 1;

                }else{

                    prec2 = 2;

                }

                if(prec2 < prec1){//若是當前運算符比s1棧頂運算符優先級高,則將運算符壓入s1

                    s1.push(opTop);

                    break;

                }else{//若是當前運算符與棧頂運算符相同或者小於優先級別,那麼將S1棧頂的運算符彈出並壓入到S2中

                    //而且要再次再次轉到while循環中與 s1 中新的棧頂運算符相比較;

                    s2.push(opTop);

                }

            }

             

        }//end while

        //若是s1爲空,則直接將當前解析的運算符壓入s1

        s1.push(opThis);

    }

     

    //當前字符是 ')' 時,若是棧頂是'(',則將這一對括號丟棄,不然依次彈出s1棧頂的字符,壓入s2,直到遇到'('

    public void gotParen(char ch){

        while(!s1.isEmpty()){

            char chx = s1.pop();

            if(chx == '('){

                break;

            }else{

                s2.push(chx);

            }

        }

    }

 

}

  3、測試

1

2

3

4

5

6

7

8

9

10

@Test

public void testInfixToSuffix(){

    String input;

    System.out.println("Enter infix:");

    Scanner scanner = new Scanner(System.in);

    input = scanner.nextLine();

    InfixToSuffix in = new InfixToSuffix(input);

    MyCharStack my = in.doTrans();

    my.displayStack();

}

  4、結果

  

   5、分析

  

 

  ②、計算機如何實現後綴表達式的運算?

  

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

package com.ys.poland;

 

public class CalSuffix {

    private MyIntStack stack;

    private String input;

     

    public CalSuffix(String input){

        this.input = input;

        stack = new MyIntStack(input.length());

         

    }

     

    public int doCalc(){

        int num1,num2,result;

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

            char c = input.charAt(i);

            if(c >= '0' && c <= '9'){

                stack.push((int)(c-'0'));//若是是數字,直接壓入棧中

            }else{

                num2 = stack.pop();//注意先出來的爲第二個操做數

                num1 = stack.pop();

                switch (c) {

                case '+':

                    result = num1+num2;

                    break;

                case '-':

                    result = num1-num2;

                    break;

                case '*':

                    result = num1*num2;

                    break;

                case '/':

                    result = num1/num2;

                    break;

                default:

                    result = 0;

                    break;

                }//end switch

                 

                stack.push(result);

            }//end else

        }//end for

        result = stack.pop();

        return result;

    }

     

    public static void main(String[] args) {

        //中綴表達式:1*(2+3)-5/(2+3) = 4

        //後綴表達式:123+*123+/-

        CalSuffix cs = new CalSuffix("123+*523+/-");

        System.out.println(cs.doCalc()); //4

    }

 

}

四、前綴表達式

  前綴表達式,指的是不包含括號,運算符放在兩個運算對象的前面,嚴格從右向左進行(再也不考慮運算符的優先規則),全部的計算按運算符出現的順序。

  注意:後綴表達式是從左向右解析,而前綴表達式是從右向左解析。

  ①、如何將中綴表達式轉換爲前綴表達式?

  

 

  ②、計算機如何實現前綴表達式的運算?

  

相關文章
相關標籤/搜索