1. 程式人生 > 實用技巧 >字首表示式、中綴表示式、字尾表示式的定義及實現

字首表示式、中綴表示式、字尾表示式的定義及實現

定義

  1. 中綴表示式:平常我們手動輸入的表示式、計算式,都是中綴表示式,按照我們理解的運算優先順序進行計算。按照人的思維方式進行表示式的輸入,最終輸出預期結果。比如 1 + (2 + 3) × 4 - 5
  2. 字尾表示式、字首表示式:雖然中綴表示式是按照我們肉眼的運算子優先順序寫出的,但是最終實現這個運算的,比如計算器是沒有這麼智慧的,計算器只會按照輸入的運算子一個一個的進行計算。這時候就用到了字尾、字首表示式。比如:字尾表示式針對於上面的就是 1 2 3 + 4 × + 5 -

手動實現

  1. 那麼我們怎麼實現中綴轉換為字尾呢?

    手動實現:把所有運算按照優先順序加上括號,然後把運算子號移動到括號前面,然後去除括號。

    比如:1 + (2 + 3) × 4 - 5

    加括號:

    1 +( (2 + 3) × 4 ) - 5

    (1 +( (2 + 3) × 4 )) - 5

    ((1 +( (2 + 3) × 4 )) - 5)

    運算子號後移,並去除括號:

    1 2 3 + 4 × + 5 -

    字首表示式,就是符號前移,一樣的

2.計算機怎麼去識別字尾呢

​ 使用大名鼎鼎的棧就很方便的實現了

​ 棧的特點是先進後出,後進先出

​ 針對於字尾表示式

1. 遇到數字入棧

2. 遇到運算子,彈出棧的兩個數字,然後和運算子進行運算
3. 重複過程
4. 因為字尾表示式,其實已經是把運算子優先順序順序換一種表示形式,展現出來了而已

程式實現

​ 說了一大推,我們首先來看一下程式上的實現一個對中綴表示式進行輸入,然後進行轉換,並進行結果的輸出

​ 步驟

1. 中綴表示式轉化為字尾表示式
2. 進行字尾表示式的計算

第一步

​ 程式思路:

  1. 定義棧S1,儲存運算子。定義棧S2,儲存數字和運算子,儲存最終的字尾表示式

  2. 對於新字元進行判斷只要新字元不等於‘\0’,一直進行下面的迴圈:

    1. 如果S1的大小為空, 字元入S1

    2. 如果是( 入棧

    3. 如果是),將S1知道(之前的運算子出棧,新增到S2中

    4. 如果S1的大小不為空,並且S1棧頂的運算子優先順序大於當前的新字元或者兩個字元是相等的

      那麼當前的S1棧頂就可以出棧,新增到S2中

      新字元入棧S1

    5. 如果新字元的範圍是‘0’ - ’9‘之間,那麼新字元新增進S2中

    6. 否則,新增到S1中

  3. 跳出迴圈後,如果S1的size不為空,把S1的運算子一一彈出,新增到S2中,最終S2就是排列好的字尾表示式

  4. 然後就可以進行運算

    程式碼,使用c++

    int weight(const char code) {
        if((code == '+')
           || (code == '-')) {
            return 1;
        }
        else if((code == '*')
           || (code == '/')) {
            return 2;
        }
    }
    
    bool priority(const char left, const char right) {
        if(left == '(') {
            return false;
        }
        else if(weight(left) < weight(right)) {
            return false;
        }
        else {
            return true;
        }
    }
    
    
    
    bool caculation(const char* input, LinkStack<char>& S2) {
    
        if(input == NULL) {
            return false;
        }
    
        bool ret = true;
        LinkStack<char> S1;
    
        int i = 0;
    
        int out_index = 0;
        while(ret && (input[i] != '\0')) {
            if(input[i] == '(') {
                S1.push(input[i]);
    
            }
    
            else if((S1.size() > 0) && (input[i] == ')')) {
    
                char code = S1.get();
    
                while(code != '(') {
                    S2.push(code);
                    S1.pop();
                    code = S1.get();
                }
    
                if(code == '(') {
                    S1.pop();
                }
            }
    
            else if((S1.size() > 0) && priority(S1.get(), input[i])) {
                std::cout << "13" << std::endl;
                char code = S1.get();
                S2.push(code);
                S1.pop();
                S1.push(input[i]);
            }
    
            else if( (input[i] >= '0') && (input[i] <= '9')) {
                S2.push(input[i]);
            }
    
            else {
                S1.push(input[i]);
            }
    
            i++;
        }
    
        while(S1.size() > 0) {
            char code = S1.get();
            S2.push(code);
            S1.pop();
        }
    
        return ret;
    }
    
    
    1. 核心函式就是上面的兩個,輸入引數1是中綴表示式,輸入引數2是棧,最終棧中儲存排序好的字尾表示式
    2. 拿一個例子來演示一下:
      6.

說明

  字尾表示式,這種方式後計算優點也很大,直接從上到下,數字就入棧,符號就把當前棧中的連續兩個彈出,然後和當前符號進行運算,然後再入數字棧。