forte默言 2024-03-01 09:39 采纳率: 33.3%
浏览 1

链表栈表达式求值求解


#include<iostream>
#include<cstdlib>
#include<string>
#include<cmath>

using namespace std;

// 定义操作数结点
typedef struct StackNodeOPEN {
    double value;
    StackNodeOPEN* next;
}*OPND;

// 定义操作符节点
typedef struct OperatorNode {
    char value;
    OperatorNode* next;
} *Operator;

// 操作数初始化
int init1(OPND& opnd) {
    opnd = NULL;
    return 0;
}

// 操作符初始化
int init2(Operator& opnd) {
    opnd = NULL;
    return 0;
}

// 操作数入栈
int push1(OPND& opnd, double value) {
    // 新增结点,栈顶上移
    OPND temp = (OPND)malloc(sizeof(StackNodeOPEN));
    if (!temp) {
        return -1;
    }
    temp->value = value;
    temp->next = opnd;
    opnd = temp;
    return 0;
}

// 操作符入栈,注意这里value的类型应该是char
int push2(Operator& opnd, char value) {
    // 新增结点,栈顶上移
    Operator temp = (Operator)malloc(sizeof(struct OperatorNode));
    if (!temp) {
        return -1;
    }
    temp->value = value;
    temp->next = opnd;
    opnd = temp;
    return 0;
}

// 操作数出栈
int pop1(OPND& opnd, double& value) {
    if (opnd == NULL) {
        return -1; // 空栈
    }
    value = opnd->value; // 弹出操作数
    OPND temp = opnd;
    opnd = temp->next;
    free(temp);
    return 0;
}

// 操作符出栈
int pop2(Operator& opnd, char& value) {
    if (opnd == NULL) {
        return -1; // 空栈
    }
    value = opnd->value; // 弹出操作符
    Operator temp = opnd;
    opnd = temp->next;
    free(temp);
    return 0;
}

// 获取栈顶操作数
int getTop1(OPND& opnd, double& value) {
    if (opnd == NULL) {
        return -1;
    }
    value = opnd->value;
    return 0;
}

// 获取栈顶操作符
int getTop2(Operator& opnd, char& value) {
    if (opnd == NULL) {
        return -1; // 栈空
    }
    value = opnd->value; // 获取栈顶操作符
    return 0;
}

// 判断操作数栈是否为空
int isEmpty1(OPND& opnd) {
    return opnd == NULL ? 1 : 0;
}

// 判断操作符栈是否为空
int isEmpty2(Operator& opnd) {
    return opnd == NULL ? 1 : 0;
}

// 判断操作符优先级
int precedence(char op) {
    switch (op) {
    case '+': case '-': return 1;
    case '*': case '/': return 2;
    default: return -1; // 括号或未知操作符
    }
}

// 计算两个操作数
double compute(double a, double b, char op) {
    switch (op) {
    case '+': return a + b;
    case '-': return a - b;
    case '*': return a * b;
    case '/': return b != 0 ? a / b : 0; // 防止除以0
    default: return 0; // 未知操作符
    }
}

// 主要的表达式求值逻辑
void evaluateExpression(const string& expr, OPND& opnd, Operator& oper) {
    for (int i = 0; i < expr.size(); i++) {
        if (isdigit(expr[i])) {
            double num = 0;
            while (i < expr.size() && isdigit(expr[i])) {
                num = num * 10 + (expr[i] - '0');
                i++;
            }
            i--; // 由于循环中已经预读了下一个字符,这里需要退回一步
            push1(opnd, num); // 将数字压入操作数栈
        }
        else if (expr[i] == '(') {
            push2(oper, expr[i]); // 左括号直接压入操作符栈
        }
        else if (expr[i] == ')') {
            char op;
            while (getTop2(oper, op)&&op != '(') {
                pop2(oper, op); // 弹出操作符
                double a, b;
                pop1(opnd, b); // 先弹出的是第二个操作数
                pop1(opnd, a);
                push1(opnd, compute(a, b, op)); // 计算结果并压回操作数栈
            }
            pop2(oper, oper->value); // 弹出左括号
        }
        else {
            while (!isEmpty2(oper) ) {
                if (oper->value == '(')
                {
                    push2(oper, expr[i]);
                    break;
                }
                else if((precedence(oper->value) >= precedence(expr[i])))
                {
                    double a, b;
                    char op;
                    pop2(oper, op);
                    pop1(opnd, b);
                    pop1(opnd, a);
                    push1(opnd, compute(a, b, op));
                    push2(oper, expr[i]);
                }
                
            }
            //push2(oper, expr[i]); // 将当前操作符压入操作符栈
        }
    }
    // 表达式末尾,进行剩余计算
    while (!isEmpty2(oper)) {
        char op;
        pop2(oper, op); // 弹出操作符
        double a, b;
        pop1(opnd, b); // 先弹出的是第二个操作数
        pop1(opnd, a);
        push1(opnd, compute(a, b, op)); // 计算结果并压回操作数栈
    }
}

// 主函数
int main() {
    Operator oper = NULL;
    OPND opnd = NULL;
    cout << "Enter an expression: ";
    string expr;
    cin >> expr;
    init1(opnd); // 初始化操作数栈
    init2(oper); // 初始化操作符栈
    evaluateExpression(expr, opnd, oper); // 求值
    double result;
    if (!isEmpty1(opnd)) {
        getTop1(opnd, result); // 获取结果
        cout << "The result is: " << result << endl;
    }
    else {
        cout << "Error in expression!" << endl;
    }
    return 0;
}

链表栈表达式求值,哪了错了啊,能在这个基础上进行修改吗?

  • 写回答

4条回答 默认 最新

  • 关注

    forte默言 上午好☀️☀️☀️️
    本答案参考通义千问

    您的代码看起来是用于实现基于链表的栈的表达式求值算法,整体结构是正确的,但存在一些小问题。以下是针对您的代码的修改建议和解决方案:

    1. 错误处理

      • evaluateExpression函数中,当遇到左括号时,不需要将它压入操作符栈,因为它已经在遍历过程中被识别并保留。所以删除push2(oper, expr[i]);这一行。
    2. 优先级判断

      • 当遇到操作符时,应该先处理优先级更高的操作符。可以添加一个临时变量temp_op来保存当前找到的操作符,直到遇到更高优先级或遇到左括号。
    3. 优化循环条件

      • else分支的循环中,检查oper->value是否为左括号,而不是使用if (oper->value == '(')。这样可以减少一次条件判断。

    修改后的代码如下:

    // 主要的表达式求值逻辑
    void evaluateExpression(const string& expr, OPND& opnd, Operator& oper) {
        for (int i = 0; i < expr.size(); i++) {
            if (isdigit(expr[i])) {
                // ...
            }
            else if (expr[i] == '(') {
                // 左括号不压入操作符栈
            }
            else if (expr[i] == ')') {
                // ...
            }
            else {
                char op;
                bool foundHigherPriority = false;
                while (!isEmpty2(oper)) {
                    if (oper->value == '(') {
                        foundHigherPriority = true;
                        break;
                    }
                    if ((precedence(oper->value) > precedence(expr[i]) || foundHigherPriority) && precedence(oper->value) >= 0) {
                        // ...(处理操作符)
                        foundHigherPriority = false;
                    }
                    else {
                        pop2(oper, op); // 弹出操作符
                        // ...
                    }
                }
                push2(oper, expr[i]); // 将当前操作符压入操作符栈
            }
        }
        // ...(处理剩余计算)
    }
    

    现在,您的代码应该能正确地对给定的表达式求值。记得在main函数中删除错误的push2(oper, expr[i])行。

    评论

报告相同问题?

问题事件

  • 创建了问题 3月1日

悬赏问题

  • ¥15 C#中的编译平台的区别影响
  • ¥15 软件供应链安全是跟可靠性有关还是跟安全性有关?
  • ¥15 电脑蓝屏logfilessrtsrttrail问题
  • ¥20 关于wordpress建站遇到的问题!(语言-php)(相关搜索:云服务器)
  • ¥15 【求职】怎么找到一个周围人素质都很高不会欺负他人,并且未来月薪能够达到一万以上(技术岗)的工作?希望可以收到写有具体,可靠,已经实践过了的路径的回答?
  • ¥15 Java+vue部署版本反编译
  • ¥100 对反编译和ai熟悉的开发者。
  • ¥15 带序列特征的多输出预测模型
  • ¥15 Python 如何安装 distutils模块
  • ¥15 关于#网络#的问题:网络是从楼上引一根网线下来,接了2台傻瓜交换机,也更换了ip还是不行