C++ 数据结构 栈 中缀表达式转后缀表达式并求值

这篇具有很好参考价值的文章主要介绍了C++ 数据结构 栈 中缀表达式转后缀表达式并求值。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面,这里用的是我自己写的Stack类,并非STL,实现方法为静态数组,但使用过程中的函数方法一样,无伤大雅。(完整code和Stack_static类赋在最后)

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

1.从左到右遍历

2.数,即参与运算数,直接放进后缀表达式之后

3.左括号,直接压入栈(因为括号的优先级最高,无需判断)(入栈后优先级最低,确保其它的符号正常入栈)

4.右括号,意味着括号已经结束,那么不断弹出栈顶,直到遇到左括号。

5.运算符,将该运算符与栈顶运算符进行比较

        如果优先级高于栈顶运算符则压入堆栈

        如果优先级低于或等于栈顶运算符则将栈顶运算符弹出并放入后缀表达式中

        ***这里是核心,低于或等于栈顶元素意味着前面部分可以运算了,先放入表达式,即先进行运算的一定是高优先级的运算符。

        直到优先级大于栈顶运算符或者栈空,再将该运算符入栈。

6.对字符串处理完毕后,则按顺序弹出栈中所剩运算符,放入表达式中

这里我给出一个例子:2+(3*(4-1))+3

C++ 数据结构 栈 中缀表达式转后缀表达式并求值

code中的栈类是我自己写的类,不是STL中的,但功能大致一样,

/*
返回运算符的优先级
*/
int value(char c){
    switch(c){
        case '(':
            return 0;
            break;
        case '+':
        case '-':
            return 1;
            break;
        case '*':
        case '/':
            return 2;
            break;
        default:
            cout<<"input error"<<endl;
            return 0;
    }
}

//将中缀表达式转化成后缀表达式
string change(string str){
    string changed = "";
    Stack_static s;
    int opflag = 1;//记录运算符是否出现,用于判断-是负号还是减号。
    for(int i = 0; i < int(str.length());i++){
        if(str[i]>='0' && str[i]<='9'){//若为数字,则直接接到后缀表达式后面
            changed += str[i];
            opflag = 0;
        }
        else if(str[i]=='('){//若为左括号,直接压入栈
            s.push(str[i]);
        }
        else if(str[i]==')'){//若为右括号,一直出栈接入后缀表达式,直到遇到左括号
            while(s.top()!='('){
                changed += ' ';
                changed += s.top();
                s.pop();
                if(s.empty())break;
            }
            s.pop();
        }
        else{
            if(opflag){
                changed += str[i];
                opflag = 0;
            }
            else{
                changed += ' ';//遇到正常的符号,说明一个数字已经输入完毕,所以加一个空格隔开个个数字
                if(s.empty())s.push(str[i]);//若栈空,则直接入栈
                else if(value(str[i]) > value(s.top()))s.push(str[i]);//若优先级大于栈顶,直接入栈
                else {//若优先级小于等于前一个,则不断比较并出栈
                    while(value(str[i]) <= value(s.top())){
                        changed += s.top();
                        changed += ' ';
                        s.pop();
                        if(s.empty())break;//如果空了,退出循环
                    }
                    s.push(str[i]);
                }
                opflag = 1;
            }
        }
    }
    while(!s.empty()){//当结束时,栈不为空,则一个一个出栈
        changed += ' ';
        changed += s.top();
        s.pop();
    }
    return changed;//返回最终的后缀表达式
}

接下来是后缀表达式的求值方法

1.依旧是从左到右遍历字符串

2.数,这次的数的处理是直接压入栈

3.符号,若是空格,则将前面保存的数压入栈(因为数可能是多位数,所以不能直接压入栈,有别于转后缀。所以我们需要一个数来保存字符输进来的数字。)

4.运算符,碰到一个运算符,我们就进行一次计算,对栈顶的两个数字进行计算,这也就是后缀表达式的计算原理

接下来举个例子,式子与上面的相同

后缀表达式为2 3 4 1-* 3++

C++ 数据结构 栈 中缀表达式转后缀表达式并求值

最后所剩的14即为最终答案,直接输出即可

下面是实现的代码

//计算两个数,用于弹出的运算符和两个数
double calculate(double x,double y,char c){
    switch (c)
    {
    case '+':
        return x+y;
        break;
    case '-':
        return x-y;
        break;
    case '*':
        return x*y;
        break;
    case '/':
        if(!y){
            cerr<<"除数不能为0"<<endl;
            exit(0);
        }
        return x/y;
        break;
    default:
        cerr<<"input error"<<endl;
        exit(0);
        break;
    }
}

//计算后缀表达式的值
double result(string str){
    Stack_static S_num;
    int num = 0,flag = 0,fu_flag = 0;
    for(int i = 0;i < int(str.length());i++){
        if(str[i]>='0' && str[i]<='9'){//遇到数字存入num中
            num = num*10 + str[i]-'0';
            flag = 1;//flag用来记录现在数字是否存在
        }
        else{
            if(flag){//避免连续读入字符时,数字栈中存入多个0
                if(fu_flag)//如果是负数
                    S_num.push(-double(num));
                else
                    S_num.push(double(num));
                flag = 0;
                fu_flag = 0;
                num = 0;//置0
            }
            if(str[i]==' '){
                fu_flag = 0;
                continue;
            }
            if(str[i]=='-' && str[i+1]>='0' && str[i+1]<='9'){
                fu_flag = 1;
                continue;
            }
            
            double a,b;
            a = S_num.top();//取出栈顶
            S_num.pop();
            b = S_num.top();//取出栈顶
            S_num.pop();
            S_num.push(calculate(b,a,str[i]));//计算后压入栈
        }
    }
    return S_num.top();
}

我的Stack_static类,是静态数组的实现

#include<iostream>
const int STACK_MAX = 128;
typedef int StackElement;
class Stack_static
{
private:
    StackElement myArray[STACK_MAX];
    int myTop;
public:
    Stack_static();
    ~Stack_static();
    void push(const StackElement &value);
    void pop();
    StackElement top();
    bool empty();
    void display(std::ostream & out);
    int get_myTop(){
        return myTop;
    }
    StackElement bottom();
};

Stack_static::Stack_static()
{
    myTop = -1;
}

Stack_static::~Stack_static()
{
}

bool Stack_static::empty(){
    if(myTop==-1)return true;
    return false;
}

StackElement Stack_static::top(){
    if( !empty())
        return myArray[myTop];
    else{
        std::cerr << "*** Stack is empty -- return ***\n";
        StackElement garbage=0;
        return garbage;
    }
}

void Stack_static::push(const StackElement &value){
    if(myTop < STACK_MAX-1){
        myTop++;
        myArray[myTop] = value;
    }
    else{
        std::cerr << "*** Stack full -- can't add new value ***\n";
        exit(1);
    }
}

void Stack_static::pop(){
    if(!empty())
        myTop--;
    else    
        std::cerr << "*** Stack is empty***\n";
}

void Stack_static::display(std::ostream &out){

    
    for(int i = myTop-1;i >= 0; i-- ){
        out<< myArray[i] << std::endl;
    }
}

StackElement Stack_static::bottom(){
    if(!empty()){
        return myArray[0];
    }
    else{
        std::cerr<<"*** Stack is empty!***\n";
        StackElement garbage=0;
        return garbage;
    }
}

整个代码以及测试:文章来源地址https://www.toymoban.com/news/detail-434920.html

#include"Stack_static.h"
#include<iostream>
using namespace std;

//简易计算器,只包含+-*/()

/*
返回运算符的优先级
*/
int value(char c){
    switch(c){
        case '(':
            return 0;
            break;
        case '+':
        case '-':
            return 1;
            break;
        case '*':
        case '/':
            return 2;
            break;
        default:
            cout<<"input error"<<endl;
            return 0;
    }
}

//计算两个数,用于弹出的运算符和两个数
double calculate(double x,double y,char c){
    switch (c)
    {
    case '+':
        return x+y;
        break;
    case '-':
        return x-y;
        break;
    case '*':
        return x*y;
        break;
    case '/':
        if(!y){
            cerr<<"除数不能为0"<<endl;
            exit(0);
        }
        return x/y;
        break;
    default:
        cerr<<"input error"<<endl;
        exit(0);
        break;
    }
}

//将中缀表达式转化成后缀表达式
string change(string str){
    string changed = "";
    Stack_static s;
    int opflag = 1;//记录运算符是否出现,用于判断-是负号还是减号。
    for(int i = 0; i < int(str.length());i++){
        if(str[i]>='0' && str[i]<='9'){//若为数字,则直接接到后缀表达式后面
            changed += str[i];
            opflag = 0;
        }
        else if(str[i]=='('){//若为左括号,直接压入栈
            s.push(str[i]);
        }
        else if(str[i]==')'){//若为右括号,一直出栈接入后缀表达式,直到遇到左括号
            while(s.top()!='('){
                changed += ' ';
                changed += s.top();
                s.pop();
                if(s.empty())break;
            }
            s.pop();
        }
        else{
            if(opflag){
                changed += str[i];
                opflag = 0;
            }
            else{
                changed += ' ';//遇到正常的符号,说明一个数字已经输入完毕,所以加一个空格隔开个个数字
                if(s.empty())s.push(str[i]);//若栈空,则直接入栈
                else if(value(str[i]) > value(s.top()))s.push(str[i]);//若优先级大于栈顶,直接入栈
                else {//若优先级小于等于前一个,则不断比较并出栈
                    while(value(str[i]) <= value(s.top())){
                        changed += s.top();
                        changed += ' ';
                        s.pop();
                        if(s.empty())break;//如果空了,退出循环
                    }
                    s.push(str[i]);
                }
                opflag = 1;
            }
        }
    }
    while(!s.empty()){//当结束时,栈不为空,则一个一个出栈
        changed += ' ';
        changed += s.top();
        s.pop();
    }
    return changed;//返回最终的后缀表达式
}

//计算后缀表达式的值
double result(string str){
    Stack_static S_num;
    int num = 0,flag = 0,fu_flag = 0;
    for(int i = 0;i < int(str.length());i++){
        if(str[i]>='0' && str[i]<='9'){//遇到数字存入num中
            num = num*10 + str[i]-'0';
            flag = 1;//flag用来记录现在数字是否存在
        }
        else{
            if(flag){//避免连续读入字符时,数字栈中存入多个0
                if(fu_flag)//如果是负数
                    S_num.push(-double(num));
                else
                    S_num.push(double(num));
                flag = 0;
                fu_flag = 0;
                num = 0;//置0
            }
            if(str[i]==' '){
                fu_flag = 0;
                continue;
            }
            if(str[i]=='-' && str[i+1]>='0' && str[i+1]<='9'){
                fu_flag = 1;
                continue;
            }
            
            double a,b;
            a = S_num.top();//取出栈顶
            S_num.pop();
            b = S_num.top();//取出栈顶
            S_num.pop();
            S_num.push(calculate(b,a,str[i]));//计算后压入栈
        }
    }
    return S_num.top();
}

//测试代码
int main(){
    string a;
    cout << "Infix expression?";
    cin >> a;
    cout << "Postfix expression is " << change(a) << endl;
    cout << "Result:" << result(change(a));
    return 0;
}

到了这里,关于C++ 数据结构 栈 中缀表达式转后缀表达式并求值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构——前缀、中缀、后缀表达式实现和转换(Java)

    1.7.1 概念 它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。它们之间的区别在于 运算符相对与操作数的位置 不同 前缀 表达式的运算符位于与其相关的 操作数之前 ;中缀和后缀同理。 平时我们 日常使用 并最为熟悉的就是中缀表达式。如: 1 + 2 *

    2024年02月05日
    浏览(52)
  • 【尚硅谷】数据结构和算法——前缀、中缀、后缀表达式规则

    跟着B站的尚硅谷学习数据结构与算法,语言为java,目前是第七个代码内容——前缀、中缀、后缀表达式 课程传送门:尚硅谷——前缀、中缀、后缀表达式 1)前缀表达式又称波兰式, 前缀表达式 的运算符位于操作符之前。 2)举例说明:(3+4)*5-6 对应的前缀表达式就是 - *

    2024年02月03日
    浏览(56)
  • 【数据结构】超详细讲解:算术表达式转化为后缀表达式、前缀表达式、表达式树的构建

    作者: 努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:算法、数据结构、Java等相关知识。 博主主页: @是瑶瑶子啦 所属专栏: 【数据结构】:该专栏专注于数据结构知识,持续更新,每一篇内容优质,浅显易懂,不失深度! 近期目标: 写好专栏

    2024年02月08日
    浏览(49)
  • 数据结构之表达式求值

     前言 运用堆栈解决表达式的求值,代码思路为: 1.定义两个栈,一个char类型的栈用于存放运算符(ysf)一个int类型的栈用于存放操作数(czs) 如一个表达式3+6*9,将“+”,“*”入ysf栈,将“3”“6”“9”入czs栈 2.运用getchar进行数据的录入,如果接收的是运算符,将其插入到运

    2024年04月29日
    浏览(34)
  • 数据结构 实验2——表达式求值

    一、实验名称:表达式求值 二、实验学时: 6 学时 三、实验目的 1.理解栈的结构特点和基本操作特性; 2.掌握利用栈实现表达式求值算法。 四、实验内容 ( 步骤 ) 输入一个算术表达式(以“=”结束),求其值。要求表达式以“=”结束,操作数为多位实数,对错误表达式要进行

    2023年04月08日
    浏览(38)
  • 数据结构 | 后缀表达式【深入剖析堆栈原理】

    Hello,大家好,国庆的第二天,带来的是数据结构中堆栈部分的后缀表达式,这也是一块有关栈的应用方面困扰了众多同学的一个大难题,今天就让我们一起解决这个难题📕 后缀表达式也称为 逆波兰表达式 ,也就是将算术运算符放在操作数的后面 例如【1 + 2 * 3】的后缀表达

    2023年04月27日
    浏览(46)
  • 【数据结构】12 堆栈应用:表达式求值

    有一个常量表达式的中缀表达式为:5 + 6 / 2 - 3 * 4,其后缀形式表示为: 5 6 2 / + 3 4 × -。后缀表达式的特点是运算符位于两个预算数之后。其前缀表达式为: - + 5 / 6 2 × 3 4。 后缀表达式相比于中缀表达式的求值要容易很多。 从左到右扫描该表达式: (1)遇见运算数5 6 2时不

    2024年02月20日
    浏览(53)
  • 【数据结构】反射、枚举以及lambda表达式

    Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任 意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信 息以及动态调用对象方法的功能称为java语言的反射

    2024年03月13日
    浏览(38)
  • 中缀表达式转后缀表达式

      一种不需要括号的后缀表达法,也把它称为 逆波兰 表示,是波兰逻辑学家卢卡西维奇(Lukasiewicz)发明的一种表示表达式的方法。   中缀表达式指的是“9+(3-1)×3+8÷2”,这种就是我们通常见到的书写算式顺序,要计算中缀表达式则首先要将字符串转换为后缀表达式,即

    2023年04月08日
    浏览(43)
  • 【数据结构】你知道波兰表达式和逆波兰表达式吗?我才知道原来栈在表达式求值中还能这样使用……

    大家好,很高兴又和大家见面啦!!! 在前面的内容中我们详细介绍了栈的第一种应用——在括号匹配问题中的应用,如果还没有阅读过的朋友可以回看前面两篇文章。在今天的内容中我们将介绍栈的另一种应用——在表达式求值中的应用。 表达式相信大家应该不陌生了,

    2024年04月27日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包