算法要求:
- 输入一个数学表达式(假定表达式输入格式合法),计算表达式结果并输出。
- 数学表达式由单个数字和运算符“+”、“-”、“*”、“/”、“(、) ”构成,例如 2 + 3 * ( 4 + 5 ) - 6 / 4。
- 变量、输出采用整数,只舍不入。
图解算法思想:
1、图中1、2、3、4~~表示操作的前后顺序
2、图中橙色栈用来处理数字,黄色用来处理运算符。
3、本图实际上将中缀转后缀、后缀求值两步整合在一起
最后一步执行:取出‘-’,然后43-6=37,作为最后结果。
程序思想流程图:
代码如下:
【实验全部代码】
#include <iostream>
#include <string>
using namespace std;
// 写一个栈的模板函数,因为下面需要用到 int 和 char 两种 stack 类型,且方法一样
template <class T>
class Stack {
private:
T data[1001];
int size; // 同时承担 top 的作用
public:
Stack() {
size = 0;
}
~Stack() {
size = 0;
}
T pop() {//出栈
size--;
return data[size];
}
void push(T a) {//入栈
data[size++] = a;
}
T front() {//返回栈顶元素
return data[size - 1];
}
void clear() {//清除栈中元素,非物理清除,仅逻辑清除
size = 0;
}
bool empty() {//判空
return (size == 0);
}
};
// 中序转后序函数
string inToSuffix(string s) {
string result = "";
int size = s.size();
Stack<char> a;
for (int i = 0; i < size; i++) {
//对括号的处理
if (s[i] == '(') {
a.push(s[i]);
} else if (s[i] == ')') {
if (!a.empty()) {
char t = a.pop();
while (t != '(' && !a.empty()) {
result.push_back(t);
t = a.pop();
}
}
//加减乘除的处理
} else if (s[i] == '+' || s[i] == '-') { // 加减的等级是最低的
while (!a.empty()) {
if (a.front() == '(') {
break;
} else { // 加减和乘除的处理方式一样,都是弹出
result.push_back(a.pop());
}
}
a.push(s[i]);
} else if (s[i] == '*' || s[i] == '/') {
while (!a.empty()) {
if (a.front() == '(') {
break;
} else if (a.front() == '*' || a.front() == '/') { // 仅仅乘除被弹出,加减留在里面
result.push_back(a.pop());
} else
break; // 如果遇到加减,则要直接 break,否则死循环
}
a.push(s[i]);
//数字的处理
} else if (s[i] >= '0' && s[i] <= '9') {
result.push_back(s[i]);
} else {
cout << "存在非法输入" << endl;
break;
}
}
while (!a.empty()) { // 最后要把栈中所有东西一一输出
result.push_back(a.pop());
}
return result;
}
int suffix_print(string s) { // 后缀表达式核心就在于运算顺序,所以中缀中的括号在后缀中已经转化为数字和运算的前后顺序
Stack<int> a;
int size = s.size();
for (int i = 0; i < size; i++) {
if (s[i] >= '0' && s[i] <= '9')
a.push(s[i] - '0');
else {
int s2 = a.pop();
int s1 = a.pop();
if (s[i] == '*') {
a.push(s1 * s2);
} else if (s[i] == '+') {
a.push(s1 + s2);
} else if (s[i] == '/') {
a.push(s1 / s2);
} else {
a.push(s1 - s2);
}
}
}
return a.front();
}
int main() {
cout << "Input" << endl;
string input;
cin >> input;
cout << "Output" << endl;
string inpute1 = inToSuffix(input);
cout << "=" << suffix_print(inpute1) << endl;
cout << "End";
return 0;
}
感悟与算法分析:
本题是实现计算器的制作。可以分为三个子问题:括号作用在数据结构中的实现、如何将中缀表达式化为后缀表达式、如何将后缀表达式的值计算出来 针对 问题一:对于一个表达式,我们采用栈的方式去存储。那么如何用栈来处理括号问题呢?
问题二:如何将中缀表达式转化为后缀表达式只要遵循下面这几个要求即可。
所以本问题可以利用多次的if判断语句,将问题分为这几种情况分别按照要求去处理 问题三:后缀表达式的求值也同样分为以下几个步骤来处理即可。
综上来说本题考察的主要是波兰表达式和逆波兰表达式的转化,以及逆波兰表达式的计算。而这些计算借助的数据结构就是栈。程序在书写的过程中最需要注意的就是if、elseif的分类处理。有一些类处理中需要用break来退出,否则会让程序进入死循环。其他一些注意点都在程序注释中标明。 |
仅供参考,一定不要直接复制!!!查重很严的!!!