描述
人們熟悉的四則運算表達式稱為中綴表達式,例如(23+34*45/(5+6+7))。在程序設計語言中,可以利用堆棧的方法把中綴表達式轉換成保值的后綴表達式(又稱逆波蘭表示法),並最終變為計算機可以直接執行的指令,得到表達式的值。
給定一個中綴表達式,編寫程序,利用堆棧的方法,計算表達式的值。
輸入
第一行為測試數據的組數N
接下來的N行,每行是一個中綴表達式。表達式中只含數字、四則運算符和圓括號,操作數都是正整數,數和運算符、括號之間沒有空格。中綴表達式的字符串長度不超過600。
輸出
對每一組測試數據輸出一行,為表達式的值
解法
該問題可以轉換為兩個子問題:
1、將中綴表達式轉換為后綴表達式
2、利用棧對后綴表達式求值
中綴表達式轉后綴表達式
算法: 可以使用棧來完成中綴表達式到后綴表達式的轉換
1、棧stack[]用來存儲操作符,top指向棧頂,但不存儲元素,top=0表示棧為空
2、從左向右遍歷中綴表達式
a.如果遇到的是操作數num,則直接輸出到后綴表達式
b.如果遇到的是操作符op,則有幾種情況:
b.1.如果op==')',則依次彈出棧頂直到彈出'(',但'('不輸出到后綴表達式
b.2:如果op=='(',則直接入棧
b.3:如果棧為空,則直接入棧
b.4:如果op的優先級高於棧頂操作符的優先級,則入棧
b.5:如果op的優先級低於或等於棧頂操作符的優先級,則依次彈出棧頂直到op的優先級高於棧頂操作符的優先級(或棧為空),再將op入棧
3、遍歷完時,如果棧仍不為空,則依次彈出棧頂直到棧為空
具體的代碼如下:
1 int mycmp(char a, char b) { 2 if(b == '(') 3 return 1;//左括號直接入棧 4 else if((b == '*' || b == '/') &&(a == '+' || a == '-' || a == '(')) 5 return 1;//*、/優先級高於+、-、(,入棧 6 else if((b == '+' || b == '-') && (a == '(')) 7 return 1;//+、-優先級高於(,入棧 8 else 9 return 0; 10 } 11 12 /*中綴表達式轉后綴表達式 13 中綴表達式之間無分割 14 后綴表達式操作數、操作符之間用空格分割,便於區分不同操作數*/ 15 void infix_to_suffix(char* infix, char* suffix) { 16 int i, k, j=0, top=0; 17 char stack[1000];//存儲運算符的棧 18 19 for(i=0; infix[i]!='\0'; i++) { 20 if(infix[i] >= '0' && infix[i] <= '9') { 21 suffix[j++] = infix[i];//操作數則直接輸出 22 } else { 23 if(i != 0 && infix[i-1] >= '0' && infix[i-1] <= '9') { 24 suffix[j++] = ' ';//操作數后補充空格分割 25 } 26 if(infix[i] == ')') { 27 //遇到右括號則一直彈出直到左括號,但左括號不輸出 28 while(stack[top-1] != '(') { 29 suffix[j++] = stack[--top]; 30 suffix[j++] = ' '; 31 } 32 top--; 33 } else if(top == 0 || mycmp(stack[top-1], infix[i])) { 34 //棧為空或當前操作符的優先級高於棧頂操作符,當前操作符入棧 35 stack[top++] = infix[i]; 36 } else { 37 //當前操作符優先級等於或低於棧頂操作符則彈出棧頂 38 while(!mycmp(stack[top-1], infix[i])) { 39 suffix[j++] = stack[--top]; 40 suffix[j++] = ' '; 41 if(top == 0) 42 break; 43 } 44 stack[top++] = infix[i];//當前操作符入棧 45 } 46 } 47 } 48 //補充空格分割 49 if(suffix[j-1] != ' ') { 50 suffix[j++] = ' '; 51 } 52 //如果操作符棧不為空,彈出所有操作符 53 while(top != 0) { 54 suffix[j++] = stack[--top]; 55 suffix[j++] = ' '; 56 } 57 suffix[j] = '\0'; 58 }
利用棧對后綴表達式求值
算法:
1、棧stack[]用來存儲操作數,top指向棧頂,但不存儲元素,top=0表示棧為空,
2、從左向右依次遍歷后綴表達式
a.如果遇到的是操作數num,則直接將num入棧,即stack[top++]=num
b.如果遇到的是操作符op,則取出依次取出棧頂的兩個元素stack[top-2]和stack[top-1],計算stack[top-2] op stack[top-1]的結果,並將結果入棧
3、遍歷結束時,stack[top-1]即為后綴表達式求值結果
具體的C語言代碼如下:
1 /*后綴表達式求值*/ 2 int suffix_value(char* suffix) { 3 int i, j; 4 char op; 5 int stack[1000]; 6 int top = 0, value = 0; 7 for(i=0; suffix[i] != '\0'; i++) { 8 if(suffix[i] >= '0' && suffix[i] <= '9') { 9 value = value*10 + suffix[i] - '0'; 10 } else if(suffix[i] == ' ') { 11 //操作數入棧 12 stack[top++] = value; 13 value = 0; 14 } else { 15 //根據操作符,對棧頂兩個操作數進行計算並得到結果 16 switch(suffix[i]) { 17 case '+': value = stack[top-2] + stack[top-1];break; 18 case '-': value = stack[top-2] - stack[top-1];break; 19 case '*': value = stack[top-2] * stack[top-1];break; 20 case '/': value = stack[top-2] / stack[top-1];break; 21 default: break; 22 } 23 top -= 2; 24 } 25 } 26 27 return stack[0]; 28 }
至此,中綴表達式求值的主程序如下:
1 int main() { 2 int n; 3 char infix[1000], suffix[1000];//infix中綴表達式,suffix后綴表達式 4 5 scanf("%d\n", &n); 6 while(n--) { 7 gets(infix); 8 infix_to_suffix(infix, suffix); 9 printf("%d\n", suffix_value(suffix)); 10 } 11 12 return 0; 13 }