中缀表达式转化为后缀表达式

简介: 中缀表达式转化为后缀表达式

 一、后缀表达式求值

后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储。假定待求值的后缀表达式为:6 5 2 3 + 8 * + 3 + *,则其求值过程如下:

1)遍历表达式,遇到的数字首先放入栈中,此时栈如下所示:

2)接着读到“+”,则弹出3和2,执行3+2,计算结果等于5,并将5压入到栈中。

3)读到8,将其直接放入栈中。

4)读到“*”,弹出8和5,执行8*5,并将结果40压入栈中。而后过程类似,读到“+”,将40和5弹出,将40+5的结果45压入栈...以此类推。最后求的值288。

二、中缀表达式转后缀表达式

2.1)规则

中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。

转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

2.2)实例规则很多,还是用实例比较容易说清楚整个过程。以上面的转换为例,输入为a + b * c + (d * e + f)*g,处理过程如下:

1)首先读到a,直接输出。

2)读到“+”,将其放入到栈中。

3)读到b,直接输出。此时栈和输出的情况如下:

4)读到“*”,因为栈顶元素"+"优先级比" * " 低,所以将" * "直接压入栈中。

5)读到c,直接输出。此时栈和输出情况如下:

6)读到" + ",因为栈顶元素" * "的优先级比它高,所以弹出" * "并输出, 同理,栈中下一个元素" + "优先级与读到的操作符" + "一样,所以也要弹出并输出。然后再将读到的" + "压入栈中。此时栈和输出情况如下:

7)下一个读到的为"(",它优先级最高,所以直接放入到栈中。

8)读到d,将其直接输出。此时栈和输出情况如下:

9)读到" * ",由于只有遇到" ) "的时候左括号"("才会弹出,所以" * "直接压入栈中。

10)读到e,直接输出。

此时栈和输出情况如下:

11)读到" + ",弹出" * "并输出,然后将"+"压入栈中。

12)读到f,直接输出。此时栈和输出情况:

13)接下来读到“)”,则直接将栈中元素弹出并输出直到遇到"("为止。这里右括号前只有一个操作符"+"被弹出并输出。

14)读到" * ",压入栈中。读到g,直接输出。

15)此时输入数据已经读到末尾,栈中还有两个操作符“*”和" + ",直接弹出并输出。至此整个转换过程完成。程序实现代码后续再补充了。

2.3)转换的另一种方法

1)先按照运算符的优先级对中缀表达式加括号,变成( ( a+(b*c) ) + ( ((d*e)+f) *g ) )

2)将运算符移到括号的后面,变成((a(bc)*)+(((de)*f)+g)*)+

3)去掉括号,得到abc*+de*f+g*+

三、代码实现

function isOperator(value){
    var operatorString = "+-*/()";
    return operatorString.indexOf(value) > -1
}
function getPrioraty(value){
    switch(value){
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        default:
            return 0;
    }
}
function prioraty(o1, o2){
    return getPrioraty(o1) <= getPrioraty(o2);
}
function dal2Rpn(exp){
    var inputStack = [];
    var outputStack = [];
    var outputQueue = [];
    for(var i = 0, len = exp.length; i < len; i++){
        var cur = exp[i];
        if(cur != ' ' ){
            inputStack.push(cur);
        }
    }
    console.log('step one');
    while(inputStack.length > 0){
        var cur = inputStack.shift();
        if(isOperator(cur)){
            if(cur == '('){
                outputStack.push(cur);
            }else if(cur == ')'){
                var po = outputStack.pop();
                while(po != '(' && outputStack.length > 0){
                    outputQueue.push(po);
                    po = outputStack.pop();
                }
                if(po != '('){
                    throw "error: unmatched ()";
                }
            }else{
                while(prioraty(cur, outputStack[outputStack.length - 1]) && outputStack.length > 0){
                    outputQueue.push(outputStack.pop());
                }
                outputStack.push(cur);
            }
        }else{
            outputQueue.push(new Number(cur));
        }
    }
    console.log('step two');
    if(outputStack.length > 0){
        if(outputStack[outputStack.length - 1] == ')' || outputStack[outputStack.length - 1] == '('){
            throw "error: unmatched ()";
        }
        while(outputStack.length > 0){
            outputQueue.push(outputStack.pop());
        }
    }
    console.log('step three');
    return outputQueue;

image.gif


相关文章
|
Web App开发 编解码 Ubuntu
YouTube下载视频教程:常用的网站软件插件APP都有涉及
有时候可能需要YouTube上的视频来进行一些操作,比如教程演示,语言学习,视频编辑等.....那么YouTube视频怎么下载下来呢?方法比较多。在这篇文章里我会给大家介绍一些下载YouTube视频的常用网站、浏览器插件、电脑软件和手机APP,方便大家找到最合适的方法去保存油管视频。
4477 1
YouTube下载视频教程:常用的网站软件插件APP都有涉及
|
Python
Python跳动的爱心完整代码
Python跳动的爱心完整代码
2777 0
|
存储 程序员 Python
Python浪漫520表白代码
Python浪漫520表白代码
1432 0
中缀表达式转后缀表达式(逆波兰式)
中缀表达式转后缀表达式(逆波兰式)
1831 0
|
10月前
|
算法 物联网 机器人
蓝牙信标、UWB等主流室内定位无线技术的参数对比、核心算法和选型指南详解(二)
本文系统解析室内定位无线技术,涵盖蓝牙、Wi-Fi、UWB、RFID、超声波、可见光等主流技术的原理、参数对比与核心算法(RSSI、TDOA、AoA),并提供按精度、成本、场景匹配的选型指南,助力民用、工业、资产盘点及特殊环境下的最优技术选择。如果您想进一步了解定位的案例,欢迎关注、评论留言~也可搜索lbs智能定位。
|
12月前
|
机器学习/深度学习 数据采集 人工智能
【机器学习算法篇】K-近邻算法
K近邻(KNN)是一种基于“物以类聚”思想的监督学习算法,通过计算样本间距离,选取最近K个邻居投票决定类别。支持多种距离度量,如欧式、曼哈顿、余弦相似度等,适用于分类与回归任务。结合Scikit-learn可高效实现,需合理选择K值并进行数据预处理,常用于鸢尾花分类等经典案例。(238字)
|
12月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
存储 C语言
中缀表达式转后缀表达式
本文提供了一个C语言程序,用于将中缀表达式转换为后缀表达式,并计算后缀表达式的结果,包括处理运算符优先级、括号匹配以及基本的四则运算。
729 0
|
网络协议 数据安全/隐私保护 网络虚拟化
计算机网络的体系结构
OSI模型,即开放系统互连模型,由ISO于1984年提出,是计算机网络通信的参考模型,将网络功能划分为七层:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。各层负责不同的通信任务,使网络设计与管理更加模块化和高效。
1569 1
|
监控 JavaScript 网络安全