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

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

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

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

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

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

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

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

   二、四则混合运算计算器

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

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

    2.逆波兰表达式求值。

    

     生成逆波兰表达式:

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

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

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

操作符 # ^ *,/,% +,-  ( )
isp(栈内优先级) 0 7 5 3 1 8
icp(栈外优先级) 0 6 4 2 8 1

    下面是程序化算法流程:
    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

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

  1. 四则混合运算c语言程序例,C++实现四则混合运算计算器

    本文实例为大家分享了C++实现四则混合运算的计算器,供大家参考,具体内容如下 计算器是带括号的四则运算实际上利用的是栈后进先出的原则 转换思想: #define _CRT_SECURE_NO_WARN ...

  2. js实现四则混合运算计算器

    最近想用js做一个简单的计算器,不过网上的例子好像大部分都是直接从左到右挨个计算,就好像1+2*5,就会先计算1+2,再计算3*5,并没有实现运算符的优先级,这里找到了一种方法实现,来总结一下.不过这 ...

  3. python 实现四则混合运算计算器

    python 实现四则混合运算计算器 这个是基于四则混合运算计算器 Calculator的修改版,新增了处理()的功能 调试次数较少,应该尚有bug未发现,如果发现有Bug,欢迎大家来评论指正 四则混 ...

  4. python 四则混合运算计算器

    python 四则混合运算计算器 思路:(1)获取一个运算公式(四则混合) (2)对获取的公式进行处理,因为Input获取的是字符串形式,这里处 理时将之转换成列表,并对其中包含的多位数进行处理.见D ...

  5. 数据结构 用栈实现四则混合运算

    实验目的: 利用"栈"完成一定程度的四则混合运算,四则运算表达式应以字符串形式读入.该段程序要实现的基本功能是实现"十以内的加减乘除运算",在实现四则运算的简单 ...

  6. java简单运算程序_JAVA实现简单四则混合运算

    JAVA实现简单四则混合运算,说明:该计算器支持实则混合运算,如 2*(3+1 )/ 4-3 *9+ 8/ 3*4- 5,则输出:-19.333332 需要说明的事括号必须是英文的.源码如下仅供学习: ...

  7. java实现四则混合运算

    最近在看数据结构.想要实现四则混合运算.用栈来实现. 去网上看了好些代码(想偷懒来着)结果代码都不全.思路不清晰. 看的难受,最后觉得还是自己写吧.学习嘛,偷懒不得. 栈的本质就是个线性表.结构就是个 ...

  8. C语言编程学习:写的秒速计算四则混合运算项目

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  9. java 四则混合运算_Java实现四则混合运算代码示例

    使用栈来实现,可以处理运算优先级. 使用自然四则运算表达式即可,如:4+(3*(3-1)+2)/2.无需把表达式先转换为逆波兰等形式. package com.joshua.cal; import j ...

最新文章

  1. 微信小程序网络请求代码片段
  2. Nike Barkley Foamposite Max “Rayguns”
  3. Codeforces Round #479 (Div. 3)【完结】
  4. 思科怎么隐藏端口_这些著名商标下的隐藏设计,你能发现吗?
  5. xps13 linux 硬盘分区,在xps13上安装ubuntu16.04教程
  6. mscoco数据集_重磅!小目标检测的数据增广秘籍
  7. 【滤波器】基于matlab GUI高通+低通+带通+带阻FIR滤波器设计【含Matlab源码 092期】
  8. [原创]C#之探索发现:在WinForm上写的一个模拟分页小程序
  9. 宏晶新推出的STC16单片机,有哪些方面的不足?
  10. excel中的联系方式导入手机电话簿
  11. 华为USG6320做双线-基于源地址的策略路由
  12. 使用IDEA生成DOC文档
  13. 逻辑运算符:与,或,非,异或
  14. 答题小程序 服务器,答题小程序如何实现随机发题目
  15. Ewebeditor的问题
  16. OFD文件如何转换成Word?简单好用的转换方法分享
  17. 微波射频学习笔记15-------了解1/4波长天线
  18. “人不为己天诛地灭”是什么意思?_富爸爸_新浪博客
  19. 更丰富的云原生应用治理能力让业务快速生长
  20. 江苏校园舞男女生牵手用面巾纸隔开---至于吗

热门文章

  1. 74ls390设计任意进制计数器_异步FIFO:设计原理及Verliog源码
  2. 9开启线程日志_GC 日志分析
  3. python控制手机发短信_python-在python3中使用容联云通讯发送短信验证码
  4. minitab怎么算西格玛水平_六西格玛黑带培训内容
  5. c语言求跳水运动员成绩,跳水排名_C语言编程实例_C语言_最全面的网站教程
  6. app图标圆角角度_?APP图标造型分析
  7. 华为机考HJ6求质因子C语言解法
  8. 判断字符串不包含某个字符php,java判断字符串是否包含某个字符的方法
  9. C++:多线程中的小白(2)线程启动、结束、创建线程、join、detach
  10. Python Qt GUI设计:QPrinter打印图片类(基础篇—21)