实验五实现表达式求值(stack实现)

本文介绍了一种基于栈实现表达式求值的算法,通过两个栈OPTR和OPND分别存储运算符和操作数,利用优先级判断进行运算。文章详细展示了算法流程及核心代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本博文源于严蔚敏老师的《数据结构》,今天就来聊聊如何实现一位数运算数加法和多位数运算符加法。本代码完全对书中的代码再现,没有其他的过多的想法,包括多位数运算法加法也只是对原有内容基础上修改罢了。如果读者对此非常感兴趣,也可以收藏进行深度学习一波。

1、原题再现

实现表达式求值

2、测试效果

在这里插入图片描述

3、题目分析

实现表达式求值是栈的应用,一般方法如下,用两个栈,一个运算符栈,一个是操作数栈,读入字符,遇见操作数比较栈顶运算符看是否入栈,还是弹出操作数进行操作,如果遇见操作数那就入栈,具体的流程如下:

为实现运算符优先算法,可以使用两个工作栈
OPTR栈:存储运算符栈
OPND:存储操作数或运算结果
In函数:判定读入的字符ch是否为运算符
Precede 是判定运算符栈的栈顶元素与读入的元素负之间优先关系的函数
Operate:为进行二元运算

步骤如下:

    1、初始化OPTR栈和OPND栈,将表达式起始负“#”压入OPTR栈
    2、扫描表达式,读入第一个字符ch,如果表达式没有扫描完毕至"#"或OPTR的栈顶元素不为 “#”则循环执行以下操作
     2.1若ch不是运算符则压入OPND栈,读入下一个字符ch
     2.2若ch是运算符,则根据OPTR的栈顶元素和ch的优先级比较结果,做不同的处理
     2.3若是小于,则ch压入optr栈,读入下一个字符ch
     2.4若是大于,则弹出optr栈顶的运算符,从OPND栈弹出两个数,进行相应运算,借故偶压入OPND栈,
     2.5若是等于,则optr的栈顶元素是“(”且ch是”)“这时弹出OPTR栈顶的”(“相当于括号匹配成功,然后读入下一个字符1ch
    3.opnd栈顶元素即为表达式求值结果,返回此元素

核心代码

核心代码就是对这核心步骤进行实现

int main(){

    stack<int> OPND;//运算数栈
    stack<char> OPTR;//运算操符栈
    OPTR.push('#');//表达式起始”#“压入OPTR栈
    char ch;
    char theta;
    int a,b,num=0;
    cin >> ch;
    while(ch != '#' || OPTR.top()!='#'){ //表达式没有扫描完毕或OPTR的栈顶元素不为“#”
        if(!In(ch)){ //ch不是运算符则进OPND栈
            num=num*10+(ch-'0');
            cin >> ch;
            if(In(ch)) {
                OPND.push(num);
                num =0;
            }
        }else{
            switch (Precede(OPTR.top(),ch)){//比较OPTR的栈顶元素和ch的优先级
                case '<':
                    OPTR.push(ch);//当前字符ch压入optr栈,读入下一个字符ch
                    cin >> ch;
                    break;
                case '>':
                    theta = OPTR.top();OPTR.pop();//弹出OPTR栈顶元素符
                    b = OPND.top();OPND.pop();//弹出OPND栈顶的两个运算符
                    a= OPND.top();OPND.pop();
                    OPND.push(Operate(a,theta,b));//将运算结果压入OPND栈
                    break;
                case '=':
                    OPTR.pop(); //OPTR的栈顶元素是"("且ch是")"
                    cin >> ch; //弹出OPTR栈顶的"(",读入下一字符ch
                    break;
                default:
                    exit(ERROR);

            }
        }

    }

    cout << OPND.top();//求值结果
    return 0;
}

完整代码

#include<iostream>
#include<stack>
#define ERROR -1
using namespace std;

//为实现运算符优先算法,可以使用两个工作栈
//一个OPTR:寄存运算符
//OPND:寄存操作数或运算结果
//In:判定读入的字符ch是否为运算符
//Precede 是判定运算符栈的栈顶元素与读入的元素负之间优先关系的函数
//Operate:为进行二元运算
bool In(char ch){
    if(ch == '+' || ch=='-' || ch=='*' || ch=='/' || ch=='(' || ch==')' || ch=='#'){
        return true;
    }
    return false;
}
char Precede(char ch1,char ch2){
    if(ch1 =='+' || ch1 == '-'){
        if(ch2 == '*' || ch2=='/' || ch2=='('){
            return '<';
        }else{
            return '>';
        }
    }else if(ch1 == '*' || ch1=='/'){
        if(ch2 == '('){
            return '<';
        }else {
            return '>';
        }
    }else if(ch1 == '('){
        if(ch2==')'){
            return '=';
        }else if(ch2 == '#'){
            return 'E';
        }else{
            return '<';
        }
    }else if(ch1 == ')'){
        if(ch2=='('){
            return 'E';
        }else{
            return '>';
        }
    }else if(ch1 =='#'){
        if(ch2=='#'){
            return '=';
        }else if(ch2 == ')'){
            return 'E';
        }else{
            return '<';
        }
    }
    return 'E';
}
int Operate(int a,char theta,int b){
    if(theta == '+' )
        return a+b;
    else if(theta == '-')
        return a-b;
    else if(theta == '*')
        return a*b;
    else if(theta == '/')
        return a/b;
    else
        return 0;
}
int main(){
    //①初始化OPTR栈和OPND栈,将表达式起始负“#”压入OPTR栈
    //②扫描表达式,读入第一个字符ch,如果表达式没有扫描完毕至"#"或OPTR的栈顶元素不为
    // “#”则循环执行以下操作
     //若ch不是运算符则压入OPND栈,读入下一个字符ch
     //若ch是运算符,则根据OPTR的栈顶元素和ch的优先级比较结果,做不同的处理
     //若是小于,则ch压入optr栈,读入下一个字符ch
     //若是大于,则弹出optr栈顶的运算符,从OPND栈弹出两个数,进行相应运算,借故偶压入OPND栈,
     //若是等于,则optr的栈顶元素是“(”且ch是”)“这时弹出OPTR栈顶的”(“相当于括号匹配成功,然后读入下一个字符1ch
     //③ opnd栈顶元素即为表达式求值结果,返回此元素
    stack<int> OPND;//运算数栈
    stack<char> OPTR;//运算操符栈
    OPTR.push('#');//表达式起始”#“压入OPTR栈
    char ch;
    char theta;
    int a,b,num=0;
    cin >> ch;
    while(ch != '#' || OPTR.top()!='#'){ //表达式没有扫描完毕或OPTR的栈顶元素不为“#”
        if(!In(ch)){ //ch不是运算符则进OPND栈
            num=num*10+(ch-'0');
            cin >> ch;
            if(In(ch)) {
                OPND.push(num);
                num =0;
            }
        }else{
            switch (Precede(OPTR.top(),ch)){//比较OPTR的栈顶元素和ch的优先级
                case '<':
                    OPTR.push(ch);//当前字符ch压入optr栈,读入下一个字符ch
                    cin >> ch;
                    break;
                case '>':
                    theta = OPTR.top();OPTR.pop();//弹出OPTR栈顶元素符
                    b = OPND.top();OPND.pop();//弹出OPND栈顶的两个运算符
                    a= OPND.top();OPND.pop();
                    OPND.push(Operate(a,theta,b));//将运算结果压入OPND栈
                    break;
                case '=':
                    OPTR.pop(); //OPTR的栈顶元素是"("且ch是")"
                    cin >> ch; //弹出OPTR栈顶的"(",读入下一字符ch
                    break;
                default:
                    exit(ERROR);
            }
        }

    }
    cout << OPND.top();//求值结果
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值