1. 程式人生 > >利用棧的資料結構特點完成加減乘除四則運算

利用棧的資料結構特點完成加減乘除四則運算


//
//  main.cpp
//  利用棧的資料結構特點完成表示式的運算
//
//  Created by 柯木超 on 2018/12/4.
//  Copyright © 2018 柯木超. All rights reserved.
//

#include <iostream>

#define maxsize 20

/**
 解決思路:
 1、自左向右掃描表示式,凡是遇到運算元一律進運算元棧
 2、當遇到運算子時候,如果他的優先順序比運算子棧的棧頂元素(它前面的那個操作符)的優先順序低,就取出棧頂運算子和兩個連續的運算元進行運算,並將結果存入運算元棧,然後繼續比較該運算子與棧頂運算子(它前面的那個操作符)的優先順序,反之,就進棧儲存,繼續往下掃描
 3、如果遇到左括號,一律進運算子棧,右括號一律不進運算子棧,而是取出運算子棧的棧頂運算子和運算元棧的兩個運算元進行運算,並將結果押入運算元棧,直到取出左括號為止
 
 第一個例子:a + b * c,我們從前向後掃描,遇到a,壓到運算元棧裡,遇到 + ,壓到操作符棧裡,下一個是 b,此時,我們是不能像字尾表示式求值那樣,直接計算 a + b,然後壓棧的。因為我們不確定,b 是否會先參與後面的運算,所以我們只能把 b 先壓棧,繼續向後掃描。看到 * 以後,再把 * 壓到操作符棧裡;看到 c 以後,也要把 c 先壓棧,理由與 b 壓棧相同。接下來,再往下掃描,就發現已經到了末尾了。那我們就可以放心地從操作符棧裡取出頂上的操作符,在這個例子中,就是 *,然後再從運算元棧裡取出兩個運算元,就是 b 和 c,然後把b和c的積,不妨記為d,放到運算元棧裡。接下來,再去看操作符棧裡,還有一個 +,那就把 + 取出來,然後去運算元棧裡取出 a 和 d,計算它們的和,這就是最終的結果了。
 
 第二個例子:a + b + c,我們從前向後掃描,遇到a,壓到運算元棧裡,遇到 + ,壓到操作符棧裡,下一個是 b,壓到運算元棧裡。再下一個,又是 + ,由於加法的結合律,我們知道,先把a + b 的結果計算出來,或者後計算,都不會影響最終的結果。所以我們就把能做的化簡先做掉。就是說,在掃描到第二個操作符是 + 以後,我們就把第一個操作符取出來,再把兩個運算元取出來,求和並且把和送到運算元棧裡。接下來的過程與第一個例子是相同的,不再贅述了
 
 總的來說就是:
 一個操作符究竟什麼時候進行運算,並不取決於它前面的那個操作符是什麼,而是取決於它後面的那個操作符是什麼。更具體一點講:如果後面的操作符的運算優化級比前面的操作符高,那麼前面的操作符就必須延遲計算;如果後面的操作符優化級比前面的低或者相等,那麼前面的操作符就可以進行計算了
 
 參考文章:https://zhuanlan.zhihu.com/p/24556103
 **/


// 資料棧
typedef struct {
    int data[maxsize];
    int top;
}dataStask, *seqDataStask;

// 運算子棧
typedef struct {
    int data[maxsize];
    int top;
}operatorStask, *seqOperatorStask;

// 建立空棧
seqDataStask createStask(){
    seqDataStask L = (seqDataStask)malloc(sizeof(dataStask));
    L->top = -1;
    return L;
}

//  設定空棧
seqDataStask setNULLStask(seqDataStask L){
    L->top = -1;
    return L;
}

// 元素入棧
seqDataStask pushStask(seqDataStask L, int data){
    
    L->data[L->top] = data;
    L->top++;
    
    return L;
}

// 元素出棧
seqDataStask popStask(seqDataStask L, int data){
    
    L->data[L->top] = data;
    L->top--;
    
    return L;
}

// 獲取運算子的優先順序
int getPri(char cp){
    switch (cp) {
        case '+':
        case '-':
            return 1;
            break;
        case '*':
        case '/':
            return 2;
        case '(':
            return 3;
        default:
            break;
    }
    return 0;
}

int main(int argc, const char * argv[]) {
    
    return 0;
}


// 未完,待續