中缀表达式转后缀表达式:
从左到右依次遍历中缀表达式的字符
1.字符为运算数:送入后缀表达式
2.字符为左括号:左括号入栈,同时优先级降至最低
3.字符为右括号:持续出栈知道遇到左括号
4.字符为操作符:
1)栈空:入栈
2)非栈空:当前字符优先级>栈顶字符优先级,入栈,否则持续出栈直到栈顶优先级低于当前运算符优先级,当前字符入栈
遍历结束后若栈内有字符则持续出栈加到后缀表达式上。
代码:
string InfixToPostfix(string s) {//中缀表达式转后缀表达式
stack stack1(100);//初始化stack1
string ans;//存储转化后的后缀表达式
int n = s.size();
for (int i = 0; i < n; i++) {
if ((s[i] <= '9' && s[i] >= '0') or s[i] == '.') {//持续读取数字以及小数
while ((s[i] <= '9' && s[i] >= '0') or s[i] == '.') {
ans += s[i]; ++i;
}
ans +=' '; --i;//回退到当前i
}
else if (s[i] == ' ')continue;
else if (s[i] == '(')stack1.push('(');
else if (s[i] == ')') {//遇到右括号持续出栈知道匹配左括号
while (stack1.top() != '(') {
ans += stack1.top();
ans += ' ';
stack1.pop();
}
stack1.pop();
}
else {
if (s[i] == '-' && ((i>0&&s[i - 1] == '(') or i == 0)) {//如果遇到负数而返回-符号
ans += s[i];
}
else {
while (!stack1.check(s[i])) {//若栈顶优先级低于该运算符则持续出栈直到栈空或优先级不低于该运算符
ans += stack1.top();
ans += ' ';
stack1.pop();
}
stack1.push(s[i]);//该运算符入栈
}
}
}
while (!stack1.empty()) {//循环结束后栈内剩余运算符持续出栈
ans += stack1.top();
ans += ' ';
stack1.pop();
}
return ans;//返回后缀表达式
}
后缀表达式的计算:
从左到右依次遍历后缀表达式的字符
1.若为数字:入栈
2.若为运算符:栈内连续两个数字出栈,通过该运算符进行运算后重新入栈
遍历结束后最后一个数字(栈内只有一个数字)出栈,即为所得的数
代码:
double calculate(string s) {
linkStack linkStack1;
int n = s.size();
double ans;
for (int i = 0; i < n; i++) {
if (s[i] == ' ')continue;
else if (isdigit(s[i])or (i<n-1&&s[i]=='-'&&isdigit(s[i+1]))) {
double num = 0; bool fu = 0; int point=0,epoint=0;
if (s[i] == '-') { fu = 1; i++; }//判断元素是否为负数
while (isdigit(s[i]) or s[i] == '.') {
if (s[i] != '.') {num = num * 10 + s[i] - '0'; point++;}
else if (s[i] == '.') epoint = point;
i++;
}
i--;
if(epoint)
num /= pow(10, point-epoint);//若该数字存在小数点则将计算得到的值处于位于小数点后的位数的十的次方
if (fu)num *= -1;//负数将结果×-1就可以了
linkStack1.push(num);
}
else {
double a = linkStack1.top();//遇到运算符连续出栈两次
linkStack1.pop();
double b = linkStack1.top();
linkStack1.pop();
double c;//c来存储计算后的结果
if (s[i] == '+')c = a + b;
else if (s[i] == '-')c = b - a;
else if (s[i] == '*')c = a * b;
else if (s[i] == '/')c = b / a;
else if (s[i] == '%')c = double((int)b % (int)a);//需要强制转化为整型才能进行取模
else if (s[i] == '^')c = pow(b, a);
linkStack1.push(c);
}
}
ans = linkStack1.top();//返回最终结果
return ans;
}
程序完整代码,附栈的两种构造方法:
#include<iostream>
#include<string>
using namespace std;
int change(char a) {//判断运算符的优先级
if (a == '+' or a == '-')return 1;
if (a == '*' or a == '/' or a == '%')return 2;
if (a == '^')return 3;
return 0;
}
struct node {
double element;
node* next;
node() {};
node(double element) {
this->element = element;
}
node(double element, node* next) {
this->element = element; this->next = next;
}
};
class stack {
private:
int stackTop;
int length;
char* element;
public:
stack(int initialCapacity= 100);
~stack() { delete[]element; }
bool empty() { return stackTop == -1; }//判断栈是否空
char top();//读取栈顶元素
void pop();//出栈
void push(char theElement);//入栈
bool check(char theElement);//判断某一运算符是否要入栈
};
class linkStack {
private:
node* stackTop;
int length;
public:
linkStack() {stackTop = NULL; length = 0;}//构造函数
bool empty() { return length == 0; } // 判断栈是否空
double& top();//读取栈顶元素
void pop();//出栈
void push(double element);//入栈
};
stack::stack(int initialCapacity) {
if (initialCapacity < 1) { cout << "初始容量必须大于0"; return; }
length = initialCapacity;
element = new char[length];
stackTop = -1;
}
char stack::top() {
if (stackTop == -1) { cout << "栈为空"; return -1; }
return element[stackTop];
}
void stack::pop() {
if (stackTop == -1) { cout << "栈为空"; return; }
--stackTop;
}
void stack::push(char theElement) {
element[++stackTop] = theElement;
}
bool stack::check(char theElement) {
if (stackTop == -1)return 1;
int now=change(theElement), front = change(element[stackTop]);
return now > front;//判断优先级是否高于栈顶运算符
}
double& linkStack::top() {
return stackTop->element;
}
void linkStack::pop() {
node* nextNode = stackTop->next;
delete stackTop;
stackTop = nextNode;
length--;
}
void linkStack::push(double element) {
stackTop = new node(element, stackTop);
length++;
}
string InfixToPostfix(string s) {//中缀表达式转后缀表达式
stack stack1(100);//初始化stack1
string ans;//存储转化后的后缀表达式
int n = s.size();
for (int i = 0; i < n; i++) {
if ((s[i] <= '9' && s[i] >= '0') or s[i] == '.') {//持续读取数字以及小数
while ((s[i] <= '9' && s[i] >= '0') or s[i] == '.') {
ans += s[i]; ++i;
}
ans +=' '; --i;//回退到当前i
}
else if (s[i] == ' ')continue;
else if (s[i] == '(')stack1.push('(');
else if (s[i] == ')') {//遇到右括号持续出栈知道匹配左括号
while (stack1.top() != '(') {
ans += stack1.top();
ans += ' ';
stack1.pop();
}
stack1.pop();
}
else {
if (s[i] == '-' && ((i>0&&s[i - 1] == '(') or i == 0)) {//如果遇到负数而返回-符号
ans += s[i];
}
else {
while (!stack1.check(s[i])) {//若栈顶优先级<=该运算符则持续出栈直到栈空或优先级高于该运算符
ans += stack1.top();
ans += ' ';
stack1.pop();
}
stack1.push(s[i]);//该运算符入栈
}
}
}
while (!stack1.empty()) {//循环结束后栈内剩余运算符持续出栈
ans += stack1.top();
ans += ' ';
stack1.pop();
}
return ans;//返回后缀表达式
}
double calculate(string s) {
linkStack linkStack1;
int n = s.size();
double ans;
for (int i = 0; i < n; i++) {
if (s[i] == ' ')continue;
else if (isdigit(s[i])or (i<n-1&&s[i]=='-'&&isdigit(s[i+1]))) {
double num = 0; bool fu = 0; int point=0,epoint=0;
if (s[i] == '-') { fu = 1; i++; }//判断元素是否为负数
while (isdigit(s[i]) or s[i] == '.') {
if (s[i] != '.') {num = num * 10 + s[i] - '0'; point++;}
else if (s[i] == '.') epoint = point;
i++;
}
i--;
if(epoint)
num /= pow(10, point-epoint);//若该数字存在小数点则将计算得到的值处于位于小数点后的位数的十的次方
if (fu)num *= -1;//负数将结果×-1就可以了
linkStack1.push(num);
}
else {
double a = linkStack1.top();//遇到运算符连续出栈两次
linkStack1.pop();
double b = linkStack1.top();
linkStack1.pop();
double c;//c来存储计算后的结果
if (s[i] == '+')c = a + b;
else if (s[i] == '-')c = b - a;
else if (s[i] == '*')c = a * b;
else if (s[i] == '/')c = b / a;
else if (s[i] == '%')c = double((int)b % (int)a);//需要强制转化为整型才能进行取模
else if (s[i] == '^')c = pow(b, a);
linkStack1.push(c);
}
}
ans = linkStack1.top();//返回最终结果
return ans;
}
int main() {
string s;
cout << "请输入需要计算的表达式:";
getline(cin, s);
string ans1 = InfixToPostfix(s);
cout << "对应的后缀表达式为:" << ans1 << endl;;;
double ans = calculate(ans1);
cout << "计算结果为"<<ans;
}