本篇概述下运用栈(stack),将中缀表达式(infix expression)转换成后缀表达式(postfix expression),并运算结果。
1. 后缀表达式的运算。
使用栈运算后缀表达式,是最合适不过了。我们用一个简单的例子来简要Demo下。
(string/char*) 2 3 5 * + 7 8 * 对表达进行迭代。当迭代值为数字时。将其压入栈中。当迭代值为操作符时,将栈的两个元素弹出,进行运算后将结果压入栈中。
以此类推,最终获得的栈中剩余的唯一(栈顶)值为运算结果。
2.中缀表达式转后缀表达式。
中缀转后缀。记住一‘天理’般的逻辑,代码就能信手拈来了。当然这天理不是我立的 = = 感谢伟大的 Mark Allen Weiss 的著作-数据结构与算法分析。强力安利下。
开括号 ( 在栈中优先级最低,在表达式中优先级最高。加减乘除与四则运算的优先级一致。
栈元素优先级: '*' == '/' > '+' == '-' > '(' 表达式元素优先级: '(' > '*' == '/' > '+' == '-'
若迭代值为数字直接输出,遇操作符对栈中的元素进行检索。
若栈顶元素相比迭代值的优先级高或相同,输出栈顶元素,弹出,继续检索。若栈内元素优先级相比较低, 则将迭代值压入栈中。
需留意的时,栈是否为空的检测,栈为空时对操作符进行入栈操作。遇闭括号 ')' 时弹出栈中元素知道栈顶元素为开括号 '(' 。
详细过程见代码注释。
1 // 对string数式的计算(基于中缀转后缀).cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <string> 6 #include <stack> 7 #include <cctype> 8 #include <iostream> 9 10 //计算后缀表达式。(int类型) 11 int postfixExp(const std::string& exp) 12 { 13 std::stack<int> numSta; 14 for (int i = 0; i != exp.size(); i++) 15 { 16 //将表达式中的数字压入栈中 17 std::string num; 18 while (isdigit(exp[i])) 19 { 20 num.push_back(exp[i]); 21 i++; 22 } 23 24 if (!num.empty()) numSta.push(atoi(num.c_str())); 25 26 //遇到空格继续迭代 27 if (exp[i] == ' ') continue; 28 29 //遇到操作符将栈顶的两个元素弹出并将计算结果压入栈中 30 if (exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/') 31 { 32 int num1; 33 int num2; 34 if (!numSta.empty()) 35 { 36 num1 = numSta.top(); 37 numSta.pop(); 38 } 39 if (!numSta.empty()) 40 { 41 num2 = numSta.top(); 42 numSta.pop(); 43 } 44 //计算 45 switch (exp[i]) 46 { 47 case '+': numSta.push(num1 + num2); 48 break; 49 case '-': numSta.push(num2 - num1); 50 break; 51 case '*': numSta.push(num1 * num2); 52 break; 53 case '/': numSta.push(num2 / num1); 54 break; 55 default: 56 break; 57 } 58 } 59 60 } 61 return numSta.top(); 62 } 63 64 //中缀转后缀 e.g. 2 + 3 * 5 + (7 * 8 + 9) * 10 -> 2 3 5 * + 7 8 * 9 + 10 * + 65 std::string infixToPostfix(const std::string& exp) 66 { 67 std::string result; 68 std::stack<char> operators; 69 for (int i = 0; i < exp.size(); i++) 70 { 71 while (isdigit(exp[i])) 72 { 73 result.push_back(exp[i]); 74 i++; 75 } 76 //若末尾数字非个位数,数组索引将越界,由于string不是真正意义上的字符数组,越界对结果没有影响 77 //if (i >= exp.size()) break; 78 //添加空格分隔符 79 result.push_back(' '); 80 //遇到空格继续迭代 81 if (exp[i] == ' ') continue; 82 //遇到操作符时,检查栈顶元素优先级,若为高优先级/等优先级操作符,弹出栈中操作符,完成后将表达式的操作符压入 83 if (exp[i] == '+' || exp[i] == '-') 84 { 85 while (!operators.empty() && (operators.top() != '(')) 86 { 87 //当栈顶元素不为 ( 时 , ( 在栈中优先级最低,在表达式中优先级最高. 88 result.push_back(operators.top()); 89 operators.pop(); 90 result.push_back(' '); 91 } 92 operators.push(exp[i]); 93 } 94 else if (exp[i] == '*' || exp[i] == '/') 95 { 96 while (!operators.empty() && (operators.top() == '*' || operators.top() == '/')) 97 { 98 //if (operators.top() == '*' || operators.top() == '/') 若在while内进行判定,当operators不为空时将进入死循环 99 result.push_back(operators.top()); 100 operators.pop(); 101 result.push_back(' '); 102 } 103 operators.push(exp[i]); 104 } 105 else if (exp[i] == '(') operators.push('('); 106 else if (exp[i] == ')') 107 { 108 while (operators.top() != '(') 109 { 110 result.push_back(operators.top()); 111 operators.pop(); 112 result.push_back(' '); 113 } 114 //弹出 ( 115 operators.pop(); 116 } 117 118 } 119 while (!operators.empty()) 120 { 121 result.push_back(operators.top()); 122 result.push_back(' '); 123 operators.pop(); 124 } 125 126 return result; 127 } 128 129 int main() 130 { 131 std::cout << postfixExp(infixToPostfix("2 + 3 * 5 + (7 * 8 + 9) * 10")) << std::endl; 132 system("pause"); 133 return 0; 134 }