当前位置: 首页 > 编程日记 > 正文

【数据结构】支持四则混合运算的计算器(转)

1.给出两个数,用户再指定操作符,要求计算结果,这实现起来很容易;

2.多个数,但只涉及同一优先级的操作符,做起来也很容易;

3.多个数,不同优先级的操作符,怎么办呢?

想想就头痛,不过还好前人已经为我们留下了很多解决这个问题的方法。通过逆波兰表达式是解决这个问题很流行的一种方式。

一、什么是逆波兰表达式?

我们一般使用的表达式,形如1+2*3,被称为中缀表达式,转换为后缀表达式即为:1 2 3 * +,而后缀表达式也就是我们所说的逆波兰表达式。

逆波兰表达式计算起来非常方便:遇操作数入栈,遇操作符则弹出栈顶两个元素进行计算并将结果推入栈中,直至结束。上面的表达式的计算过程可以用下图表示:

也正因为逆波兰的方便性,使它成为了计算器的普遍实现方式。

二、四则混合运算计算器

既然思路已经清晰了,那么我们的计算器可以分两步走:

1.将表达式转换为逆波兰形式

2.逆波兰表达式求值。

 生成逆波兰表达式:

将一般中缀表达式转换为逆波兰表达式有如下转换过程:

(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
    (2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优 先级最低的特殊符号“#”。
    (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串 的结束并将该数字串直接输出。
    (4)如果不是数字,该字符则是运算符,此时需比较优先关系。
    做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符 栈顶的运算符,则将该运算符入栈。倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。
    (5)重复上述操作(3)-(4)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。

而上面提到的运算符优先级如下:

操作符#^*,/,%+,-()
isp(栈内优先级)075318
icp(栈外优先级)064281

下面是程序化算法流程:
    1、建立运算符栈stackOperator用于运算符的存储,压入'\0'。
    2、预处理表达式,正、负号前加0(如果一个加号(减号)出现在最前面或左括号后面,则该加号 (减号)为正负号) 。
    3、顺序扫描表达式,如果当前字符是数字(优先级为0的符号),则直接输出该数字;如果当前字 符为运算符或括号(优先级不为0的符号),则判断第4点 。
    4、若当前运算符为'(',直接入栈;
    若为')',出栈并顺序输出运算符直到遇到第一个'(',遇到的第一个'('出栈但不输出;
    若为其它,比较stackOperator栈顶元素与当前元素的优先级:
    如果 栈顶元素 >= 当前元素,出栈并顺序输出运算符直到 栈顶元素 < 当前元素,然后当前元素入栈;
    如果 栈顶元素 < 当前元素,直接入栈。
    5、重复第3点直到表达式扫描完毕。
    6、顺序出栈并输出运算符直到栈顶元素为'\0'。

a.预处理表达式,对于一元+,-在前面加0:

///<summary>
        ///处理正负号
         ///</summary>
        ///<param name="exp"></param>
        ///<returns></returns>
privatestaticstringFormatExp(stringexp)
        {
            var result =exp.Trim().Replace("", "");

            if(result[0] =='+'||result[0] =='-')
            {
                result ="0"+result;
            }
            for(var i =0; i <result.Length -1; i++)
            {
                if(result[i] =='('&&(result[i +1] =='+'||result[i +1] =='-'))
                {
                    result =result.Substring(0, i +1) +"0"+result.Substring(i +1);
                }
            }

            returnresult;
        }

b.将格式化后的表达式转换为逆波兰表达式

///<summary>
        ///将解析过后的表达式转换为逆波兰表达式(各个语义单元存放在列表中)
        ///</summary>
        ///<param name="tokens"></param>
        ///<returns></returns>
privatestaticList<string>ToRPNExp(List<string>tokens)
        {
            var result =newList<string>();
            var opStack =newStack<string>();


            opStack.Push("\0");

            for(var i =0; i <tokens.Count; i++)
            {
                if(IsOperator(tokens[i]))
                    result.AddRange(HandleOperator(opStack, tokens[i]));
                elseresult.Add(tokens[i]);
            }

            while(opStack.Peek() !="\0")
            {
                result.Add(opStack.Pop());
            }
            returnresult;
        }
        ///<summary>
        ///根据操作符的优先级决定入栈还是出栈
        ///</summary>
        ///<param name="st"></param>
        ///<param name="op"></param>
        ///<returns></returns>
privatestaticList<string>HandleOperator(Stack<string>st, stringop)
        {
            var result =newList<string>();

            if(op =="(")
            {
                st.Push(op);
            }
            elseif(op ==")")
            {
                while(st.Peek() !="(")
                {
                    result.Add(st.Pop());
                }
                st.Pop();
            }
            else
            {
                var priority1 =IcpPriority[op];
                var priority2 =IspPriority[st.Peek()];


                while(priority2 >=priority1)
                {
                    result.Add(st.Pop());
                    priority2 =IspPriority[st.Peek()];
                }
                st.Push(op);
            }
            returnresult;
        }

求值:

///<summary>
        ///进行计算
        ///</summary>
        ///<param name="tokens"></param>
        ///<returns></returns>
privatestaticdoubleDoCalc(List<string>tokens)
        {
            var st =newStack<double>();

            foreach(var token intokens)
            {
                if(!IsOperator(token))
                {
                    //操作数入栈
st.Push(double.Parse(token));
                }
                else
                {
                    //操作符从栈顶取出两个元素进行计算,并将结果推入栈中
var operand1 =st.Pop();
                    var operand2 =st.Pop();

                    switch(token)
                    {
                        case"+":
                            st.Push(operand2 +operand1);
                            break;
                        case"-":
                            st.Push(operand2 -operand1);
                            break;
                        case"*":
                            st.Push(operand2 *operand1);
                            break;
                        case"/":
                            st.Push(operand2 /operand1);
                            break;
                        case"^":
                            st.Push(Math.Pow(operand2, operand1));
                            break;

                    }
                }
            }
            //最终栈顶元素即为表达式的值
returnst.Pop();
        }

转载于:https://www.cnblogs.com/xuweili/articles/3361084.html

相关文章:

TypeScript学习笔记之 接口(Interface)

在java中&#xff0c;接口是用来定义一些规范&#xff0c;使用这些接口&#xff0c;就必须实现接口中的方法&#xff0c;而且接口中的属性必须是常量。javascript中是没有接口的概念的。所以TypeScript在编译成 JavaScript 的时候&#xff0c;所有的接口都会被擦除掉。 而TypeS…

【组队学习】【33期】数据可视化(Matplotlib)

数据可视化&#xff08;Matplotlib&#xff09; 航路开辟者&#xff1a;杨剑砺、杨煜、耿远昊、李运佳、居凤霞领航员&#xff1a;王森航海士&#xff1a;肖明远、郭棉昇 基本信息 开源内容&#xff1a;https://github.com/datawhalechina/fantastic-matplotlib开源内容&…

布尔定理及证明(完整版)

这篇文章的目的是以布尔代数公理证明定理。 对偶原理&#xff1a;0with1, with 互换以后&#xff0c;公理&#xff08;定理&#xff09;任然成立。 布尔代数的公理如下 单变量的布尔代数定理如下 单变量的布尔代数定理很容易用真值表证明。 多变量的布尔定理如下 交换律&…

创建DLL动态链接库——声明导出法

DLL声明导出法&#xff1a;是通过使用__declspec(dllexport)&#xff0c;添加到需要导出的函数前&#xff0c;进行声明。 头文件定义如下(OPdll.h)&#xff1a; 源文件定义如下(OPdll.cpp)&#xff1a; 通过以上两个文件&#xff0c;编译过后即可生成OPdll.lib和OPdll.dll两个库…

【组队学习】【33期】Scratch(一级)

Scratch一级 航路开辟者&#xff1a;王思齐、马燕鹏领航员&#xff1a;马燕鹏航海士&#xff1a;马燕鹏 基本信息 开源内容&#xff1a;https://github.com/datawhalechina/team-learning-program/tree/master/Scratch内容属性&#xff1a;公测课程内容说明&#xff1a;抽取…

Bzoj2780: [Spoj]8093 Sevenk Love Oimaster

题目 传送门 Sol 就是广义\(sam\) 然后记录下每个状态属于哪些串&#xff0c;开\(set\)维护\(parent\)树上启发式合并一下就好了 # include <bits/stdc.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; t…

LR分析法从理解到运用

1、 LR分析器 解释&#xff1a; 分析栈包括符号栈和相应状态栈 分析表包括ACTION表和GOTO表 Ⅰ动作表元素action[Si,aj] 表示当前栈顶状态为S&#xff0c;输入符号为a时所执行的动作。有四种情况&#xff1a;S(移进)&#xff0c;r(归约)&#xff0c;acc(接受)&#xff0c;erro…

Android 判断SD卡是否存在及容量查询

转载&#xff1a;http://blog.csdn.net/xinzheng_wang/article/details/7827775 Android 判断SD卡是否存在及容量查询的简单方法如下&#xff1a;首先要在AndroidManifest.xml中增加SD卡访问权限 [html] view plaincopy <!-- 在SDCard中创建与删除文件权限 --> <uses…

Spring Boot 教程(三): Spring Boot 整合Mybatis

教程简介 本项目内容为Spring Boot教程样例。目的是通过学习本系列教程&#xff0c;读者可以从0到1掌握spring boot的知识&#xff0c;并且可以运用到项目中。如您觉得该项目对您有用&#xff0c;欢迎点击收藏和点赞按钮&#xff0c;给予支持&#xff01;&#xff01;教程连载中…

电子学会 软件编程(图形化)一级训练营

「青少年编程竞赛交流群」已成立&#xff08;适合6至18周岁的青少年&#xff09;&#xff0c;公众号后台回复【Scratch】或【Python】&#xff0c;即可进入。如果加入了之前的社群不需要重复加入。 电子学会 软件编程&#xff08;图形化&#xff09;一级训练营 试题来源 青少…

win10 安装 python报错-已安装这个产品的另一版本

尝试清理干净电脑上关于之前安装的Python3&#xff0c;在 输入winR 输入cmd 回车 输入 python 回车 却看到 C:\Users\86136>python ‘python’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 但是再安装&#xff0c;又报出严重错误。 最终解决方案&am…

POJ1276Cash Machine

http://poj.org/problem?id1276 题意 &#xff1a; 给你一个目标钱数&#xff0c;再给你钱币的种数和钱币的面值&#xff0c;让你用这些钱凑出不大于目标钱数的钱然后输出这个最接近且不大于目标钱数的钱。 思路 &#xff1a; 背包问题&#xff0c;还是多重背包&#xff0c;就…

Python中处理时间 —— time模块

time模块 逝去的秒数 逝去的秒数表示从某个时间&#xff08;Python中是“Thu Jan 1 07:00:00 1970”&#xff09;开始到现在所经过的秒数。 使用 time.time() 函数可以获得逝去的秒数&#xff1a; >>time.time() 1388330058.8643time.time()返回一个浮点数&#xff0c;可…

学编程必看:逻辑思维测试

2021.09 电子学会图形化一级考试有这样的一个题目&#xff1a; 如下图所示&#xff0c;井深7米&#xff0c;有个蜗牛从井底往上爬&#xff0c;白天爬3米&#xff0c;晚上往下坠2米&#xff0c;问蜗牛几天能从井里爬出来&#xff1f;&#xff08; &#xff09; A. 4B. 5C. 6D. …

explicit specialization of ‘Race‘ after instantiation ,implicit instantiation first required here。

报错1&#xff1a; E:\project\qt\Pokemon3\PokemonServer\pokemon.cpp:470: error: specialization of ‘Race::Race() [with int N 0]’ after instantiation Race<0>::Race() : PokemonBase(ATK) ^ 报错2&#xff1a; explicit specialization of ‘Race’ after ins…

(转载)Linux usbtouchscreen驱动分析

在Linux内核中自带USB触摸屏驱动&#xff0c;以linux-2.6.33.3\drivers\input\touchscreen.c为例&#xff0c;进行解析&#xff1a; 1.驱动加载&#xff1a; static int __init usbtouch_init(void){return usb_register(&usbtouch_driver); //驱动注册} 其中usbtouch_dr…

关于事务隔离级别

2019独角兽企业重金招聘Python工程师标准>>> 第一种 read uncommitted 此状态下脏读&#xff0c;不可重复读&#xff0c;虚读都有可能发生。此状态下两个人同时操作一个数据库表一边开启事务没有提交&#xff0c;另一边也开启事物开始更改数据但是也没有提交&#x…

Datawhale组队学习周报(第047周)

本周报总结了从 2021年01月03日至2022年01月09日&#xff0c;Datawhale组队学习的运行情况&#xff0c;我们一直秉承“与学习者一起成长的理念”&#xff0c;希望这个活动能够让更多的学习者受益。 第 32 期组队学习一共 11 门开源课程&#xff0c;共组建了 11 个学习群&#…

讲座记录:从码农到架构师(精简版)

1.框架学习 不要过于在乎细节 学封装思想 不追新 否则太累 每个框架的设计理念不同 spring 比structs 优秀在哪&#xff1f; 关注增量而非全量 2.如何快速学习一门新技术 “新框架的产生速度远大于个人的学习速度” 先快速学习:了解模板&#xff0c;套路-重复出现的代码 类似做…

Enterprise Library 4 数据访问应用程序块

Enterprise Library 数据访问应用程序块简化了实现常规数据访问功能的开发任务。应用程序可以在各种场景中使用此应用程序块&#xff0c;例如为显示而读取数据、传递数据穿过应用程序层( application layers)、以及将修改的数据提交回数据库系统。应用程序块包含对存储过程和内…

虚拟货币市值回调到4100亿整数关口,EOS逆势站上100关口

虚拟货币虚拟货币市值在过去24小时中&#xff0c;虚拟货币整体回调&#xff0c;市值为4100亿美元。只有EOS逆势上扬&#xff0c;已经站上了100元&#xff08;17.5美元&#xff09;上方。虚拟货币市场距离12月份最高点几乎只有一步之遥。EOS走势EOS这种疯狂的势头是很多人预料未…

【NCEPU】韩绘锦:图信号处理与图卷积神经网络

韩绘锦是华北电力大学数理系大四的学生&#xff0c;LSGO软件技术团队&#xff08;Dreamtech算法组&#xff09;/Datawhale成员&#xff0c;也在天池比赛中取得了不错的成绩&#xff0c;现保送大连理工大学软件工程学院深造。 希望参与我们线下组队学习的同学&#xff0c;可以在…

什么是python第三方库

Python计算生态 标准库 第三方库 标准库&#xff1a;随解释器直接安装到操作系统中的功能模块 第三方库&#xff1a;需要经过安装才能使用的功能模块 模块的概念&#xff1a;库Library、包Package、模块Module 出处&#xff1a;北理工Python慕课

Task01:青少年软件编程(Scratch)等级考试模拟卷(二级)

试题来源 青少年软件编程&#xff08;Scratch&#xff09;等级考试试卷&#xff08;二级&#xff09;【2019.09】青少年软件编程&#xff08;Scratch&#xff09;等级考试试卷&#xff08;二级&#xff09;【2019.12】青少年软件编程&#xff08;Scratch&#xff09;等级考试试…

App功能测试的注意点

好几个月没有写博客记录学习心得了&#xff0c;这次回老家深夜闲来无事写一篇记录下这段时间的面试心得&#xff0c;这次面试过程很多面试官都问APP的有关测试&#xff0c;下面我就自己的认识和工作中的经验来谈谈自己对APP测试的认识&#xff1a; 1.push消息推送测试 检查push…

编程以外积累: 如何给项目生成类似VS2008的说明文档

1&#xff1a;【下载】 目前微软提供的官方开源工具 Sandcastle 结果跑到项目中一看&#xff0c;抬头就来了这么一段&#xff1a; The Sandcastle CodePlex project is no longer under active development by Microsoft and as such, there will be no future releases to t…

python的turtle绘图体系入门必看(一)

1 设置窗体 turtle.setup(width,height,startx,starty) 说明&#xff1a; setup()函数不是必须的前两个参数代表窗体的横向宽与纵向长后两个参数可选&#xff0c;表示窗体距离屏幕的横向距离和纵向距离&#xff08;也可以理解为窗体左上角距离屏幕左上角的横向和纵向距离&…

交换两个变量的值不使用第三个变量(Java)

关于这个问题网上有好多答案&#xff0c;最近有人说这是个奇葩问题 个人测试了一把&#xff0c;如果是普通的数字的话&#xff0c;基本上没有问题 public static void main(String[] args) {int a 2147483647;int b 2147483646;// aab;// ba-b;// aa-b;// b a (a b) * 0; …

Task02:青少年软件编程(Scratch)等级考试模拟卷(二级)

电子学会 软件编程&#xff08;图形化&#xff09;二级训练营 试题来源 青少年软件编程&#xff08;Scratch&#xff09;等级考试试卷&#xff08;二级&#xff09;【2019.09】青少年软件编程&#xff08;Scratch&#xff09;等级考试试卷&#xff08;二级&#xff09;【2019…

Visual Studio 15.7预览版4改进Git、C++支持

\看新闻很累&#xff1f;看技术新闻更累&#xff1f;试试下载InfoQ手机客户端&#xff0c;每天上下班路上听新闻&#xff0c;有趣还有料&#xff01;\\\对于即将到来的Visual Studio 2017 15.7&#xff0c;微软已经发布了多个新的预览版本。这些版本的变更很有限&#xff0c;似…