為了實現用棧計算算數表達式的值,需設置兩個工作棧:用于存儲運算符的棧opter,以及用于存儲操作數及中間結果的棧opval。
算法基本思想如下:
(1)首先將操作數棧opval設為空棧,而將'#'作為運算符棧opter的棧底元素,這樣的目的是判斷表達式是否求值完畢。
(2)依次讀入表達式的每個字符,表達式須以'#'結尾,若是操作數則入棧opval,若是運算符,則將此運算符c與opter的棧頂元素top比較優先級后執行相應的操作,(具體操作如下:(i)若top的優先級小于c,即top<c,則將c直接入棧opter,并讀入下一字符賦值給c;(ii)若top的優先級等于c,即top=c,則彈出opter的棧頂元素,并讀入下一字符賦值給c,這一步目的是進行括號操作;(iii)若top優先級高于c,即top>c,則表明可以計算,此時彈出opval的棧頂兩個元素,并且彈出opter棧頂的的運算符,計算后將結果放入占opval中。)直至opter的棧頂元素和當前讀入的字符均為'#',此時求值結束。
算符間的優先關系如下表所示:

表中需要注意的是θ1為opter的棧頂元素,θ2位從表達式中讀取的操作符,此優先級表可以用二維數組實現,具體見代碼(表來源:嚴蔚敏《數據結構》)。
具體代碼如下:
#include<iostream> //輸入的表達式要以'#'結尾,如‘5+6*3/(3-1)#’#include<cstring>#include<cstdio>#include<cctype>#include<stack>using namespace std;stack<char> opter; //運算符棧stack<double> opval; //操作數棧int getIndex(char theta) //獲取theta所對應的索引{ int index = 0; switch (theta) { case '+': index = 0; break; case '-': index = 1; break; case '*': index = 2; break; case '/': index = 3; break; case '(': index = 4; break; case ')': index = 5; break; case '#': index = 6; default:break; } return index;}char getPRiority(char theta1, char theta2) //獲取theta1與theta2之間的優先級{ const char priority[][7] = //算符間的優先級關系 { { '>','>','<','<','<','>','>' }, { '>','>','<','<','<','>','>' }, { '>','>','>','>','<','>','>' }, { '>','>','>','>','<','>','>' }, { '<','<','<','<','<','=','0' }, { '>','>','>','>','0','>','>' }, { '<','<','<','<','<','0','=' }, }; int index1 = getIndex(theta1); int index2 = getIndex(theta2); return priority[index1][index2];}double calculate(double b, char theta, double a) //計算b theta a{ switch (theta) { case '+': return b + a; case '-': return b - a; case '*': return b * a; case '/': return b / a; default: break; }}double getAnswer() //表達式求值{ opter.push('#'); //首先將'#'入棧opter int counter = 0; //添加變量counter表示有多少個數字相繼入棧,實現多位數的四則運算 char c = getchar(); while (c != '#' || opter.top() != '#') //終止條件 { if (isdigit(c)) //如果c在'0'~'9'之間 { if (counter == 1) //counter==1表示上一字符也是數字,所以要合并,比如12*12,要算12,而不是單獨的1和2 { double t = opval.top(); opval.pop(); opval.push(t * 10 + (c - '0')); counter = 1; } else { opval.push(c - '0'); //將c對應的數值入棧opval counter++; } c = getchar(); } else { counter = 0; //counter置零 switch (getPriority(opter.top(), c)) //獲取運算符棧opter棧頂元素與c之間的優先級,用'>','<','='表示 { case '<': //<則將c入棧opter opter.push(c); c = getchar(); break; case '=': //=將opter棧頂元素彈出,用于括號的處理 opter.pop(); c = getchar(); break; case '>': //>則計算 char theta = opter.top(); opter.pop(); double a = opval.top(); opval.pop(); double b = opval.top(); opval.pop(); opval.push(calculate(b, theta, a)); } } } return opval.top(); //返回opval棧頂元素的值}int main(){ //freopen("test.txt", "r", stdin); int t; // 需要計算的表達式的個數 cin >> t; getchar(); while (t--) { while (!opter.empty())opter.pop(); while (!opval.empty())opval.pop(); double ans = getAnswer(); cout << ans << endl<< endl; getchar(); } return 0;}結果:
![]()
新聞熱點
疑難解答