数据结构-栈:中缀表达式转后缀表达式并计算

478 阅读1分钟

中缀表达式转变成后缀表达式:

  1. 定义运算符优先级
  2. 数字直接输出
  3. 遇到操作符:
  • s1. 如果栈为空,直接入栈;
  • s2. 如果该操作符优先级大于栈顶操作符,直接入栈;
  • s3. 如果该操作符优先级低于栈顶,将栈内高(同)优先级操作符出栈,直到栈空或者遇见左括号

运算后缀表达式:

  1. 遇到操作数入栈
  2. 遇到操作符弹出两个操作数进行计算

代码实现

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <bits/stdc++.h>

using namespace std;

// 定义操作符的优先级
int priority(char opera) {
    int priorit = -1;
    switch (opera) {
        case '+':
        case '-':
            priorit = 1;
            break;
        case '*':
        case '/':
            priorit = 2;
            break;
        case '(':
            priorit = 0;
            break;
        default:
            break;
    }
    return priorit;
}

// 判断当前元素是否是操作符
bool isOper(char c) {
    return c == '+' || c == '-' || c == '*' || c == '/';
}
// 计算
bool calculateVal(char oper, int &num1, int num2) {
    switch (oper) {
        case '+':
            num1 += num2;
            break;
        case '-':
            num1 -= num2;
            break;
        case '*':
            num1 *= num2;
            break;
        case '/':
            if (0 == num2) {
                printf("除数不为0");
                return false;
            }
            num1 /= num2;
            break;
        default:
            return false;
    }
    return true;
}
/**
 * 中缀表达式转后缀
 * @param infix
 * @param suffix
 * @return
 */
bool infix2Suffix(string infix, string &suffix) {
    int len = infix.length();
    if (len == 0) return false;
    int j = 0;
    stack<char> oStack;
    for (int i = 0; i < len; i++) {
        if ('(' == infix[i]) {
            oStack.push('('); // 左括号直接入栈
        } else if (')' == infix[i]) {
            // 右括号
            while (oStack.top() != '(') {
                // 将左括号前的运算符全部出栈
                suffix += oStack.top();
                oStack.pop();
            }
            oStack.pop(); // 左括号出栈
        } else if (isdigit(infix[i])) {
            // 数字
            while (isdigit(infix[i])) {
                // 一直读到非数字的位置
                suffix += infix[i++];
            }
            i--;
            suffix += ' '; // 插入空格区分多个连续的数字
        } else if (isOper(infix[i])) {
            // 操作符
            while (!oStack.empty() && priority(infix[i]) <= priority(oStack.top())) {
                // 弹出所有优先级高于等于该操作符的操作符
                suffix += oStack.top();
                oStack.pop();
            }
            oStack.push(infix[i]);
        }
    }
    while (!oStack.empty()) { // 弹出剩余的操作符写入后缀表达式
        suffix += oStack.top();
        oStack.pop();
    }
}

bool calculateSuffix(string suffix) {
    int len = suffix.length();
    if (len == 0) return false;
    stack<int> nStack; // 操作数栈
    int num2 = 0; // 用来拼接当前连续数字
    int num1 = 0;
    for (int i = 0; i < len; ++i) {
        if (' ' == suffix[i]) {
            // 空格直接略过
            continue;
        } else if (isdigit(suffix[i])) {
            while (isdigit(suffix[i])) {
                // 将字符串中连续的单个数字拼成完整的整数
                num2 = num2 * 10 + (suffix[i++] - '0'); // char 转 int
            }
            nStack.push(num2); // 将整数压入栈中
            i--; // i 复位
            num2 = 0; // tempNum 复位,用以下次的拼接
        } else if (isOper(suffix[i])) {
            // 遇到操作符,弹出两个操作数
            num2 = nStack.top();
            nStack.pop();
            num1 = nStack.top();
            nStack.pop();
            // 计算两个数
            calculateVal(suffix[i], num1, num2);
            // 将结果重新压入栈
            nStack.push(num1);
            num2 = 0; // 复位
        }
    }
    // 计算完成后打印结果
    cout << "后缀表达式的计算结果为:" << suffix << " = " << nStack.top() << endl;
}

int main() {
    string infixString; // 前缀表达式
    string suffixString; // 后缀表达式
    while (cin >> infixString) { // 循环输入
        infix2Suffix(infixString, suffixString);
        cout << "中缀表达式转后缀表达式为: " << infixString << " = " << suffixString << endl;
        calculateSuffix(suffixString);
        suffixString.clear();
//        printf("中缀表达式: %s 转后缀为: %s",infixString,suffixString);
    }

运行结果