博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c# 逆波兰式实现计算器
阅读量:4965 次
发布时间:2019-06-12

本文共 4744 字,大约阅读时间需要 15 分钟。

语文不好,不太会组织语言,希望不要太在意。

如题,先简要介绍一下什么是逆波兰式  通常我们在写数学公式的时候  就是a+b+c这样,这种表达式称为中缀表达式,逆波兰式又称为后缀表达式,例如a+b 后缀表达式就为ab+

而把中缀表达式转为逆波兰式也是很容易的,以下算法摘自百度百科

简要说一下栈,栈是一种先进后出的对象集合,可以把栈理解为一个桶,先进后出  Stack   Peek()是取出但是不剔除 做比较的时候用,Pop()是出栈,Push()入栈

首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为输入逆波兰式的栈S2(空栈),S1栈可先放入优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。可指定其他字符,不一定非#不可。从中缀式的左端开始取字符,逐序进行如下步骤:
(1)若取出的字符是 ,则分析出完整的运算数,该操作数直接送入S2栈
(2)若取出的字符是 ,则将该运算符与S1栈栈顶元素比较,如果该 大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送入S1栈。
(3)若取出的字符是“(”,则直接送入S1栈顶。
(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个 ,依次送入S2栈,此时抛弃“(”。
(5)重复上面的1~4步,直至处理完所有的输入字符
(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。
完成以上步骤,S2栈便为逆波兰式输出结果。不过S2应做一下逆序处理。便可以按照逆波兰式的计算方法计算了!把一个表达式转为逆波兰式  比如 (a+b)*c 逆波兰式为ab+c*
a为数字,入栈,b为数字,入栈,“+”,为运算符  a b出栈,计算a+b 然后将结果 入栈,c入栈,"*"为运算符,a+b的结果出栈,c出栈,运算 * 将结果再入栈 运算完毕,栈里的结果就是我们想要的了
 
代码实现(有点乱)
 
判断元素是不是为数字
static bool IsNumber(string s)        {            return Regex.IsMatch(s, @"\d+");        }

判断元素是否为运算符(+-*/)

static bool IsSiZe(string s)        {            string ts = "+-*/";            return ts.IndexOf(s) > -1;        }

判断优先级

static int Level(string s)        {            int i = 0;            switch (s)            {                case ",":                    i = 0;                    break;                case "(":                case ")":                case "#":                    i = 1;                    break;                case "+":                case "-":                    i = 2;                    break;                case "*":                case "/":                    i = 3;                    break;            }            return i;        }

计算

private static void Calc(Stack
numStack, Stack
operStack) { int rightnum = int.Parse(numStack.Pop()); int leftnum = int.Parse(numStack.Pop()); string oper = operStack.Pop(); switch (oper) { case "+": numStack.Push((leftnum + rightnum).ToString()); break; case "-": numStack.Push((leftnum - rightnum).ToString()); break; case "*": numStack.Push((leftnum * rightnum).ToString()); break; case "/": numStack.Push((leftnum / rightnum).ToString()); break; } }

总体实现代码

static void ToNiBoLan(string exp)        {            operStack.Push("#");  //进栈  便于比较                      string token = "";             for (int i = 0; i < exp.Length; i++)            {                if (IsNumber(exp[i].ToString()))  //如果是数字                {                    token += exp[i].ToString();                }                else if (exp[i].ToString() == "(")   //左括号直接进栈                {                    operStack.Push(exp[i].ToString());                       if (IsNumber(token))                          numStack.Push(token);                    token = "";                }                else if (IsSiZe(exp[i].ToString()))                {                    if (IsNumber(token))                        numStack.Push(token);                    token = "";                    int item = Level(exp[i].ToString()).CompareTo(Level(operStack.Peek()));  //比较运算符优先级                    if (item > 0)  //如果优先级高于栈顶,运算符进栈                    {                        operStack.Push(exp[i].ToString());                    }                    else   //如果运算符小于或等于栈顶  进行计算 并将运算符进栈                    {                        Calc(numStack, operStack);                                                operStack.Push(exp[i].ToString());                    }                }                else if (exp[i].ToString() == ")")  //如果遇到右括号 依次遍历进行计算直至遇到左括号                {                    if (IsNumber(token))                        numStack.Push(token);                    token = "";                    while (operStack.Peek() != "(")                    {                        Calc(numStack, operStack);                    }                    token = numStack.Pop();  //拿出数字便于进行下一次计算                    operStack.Pop();  //符合条件的左括号出栈                                 }                else  //遍历结束                {                    if (IsNumber(token))                        numStack.Push(token);                    token = "";                    while (numStack.Count > 1)                    {                        Calc(numStack, operStack);                    }                }            }        }

  调用

string s = Console.ReadLine()+"#";  //为了便于比较,在表达式结尾加上"#"   ToNiBoLan(s);   Console.WriteLine(numStack.Pop());

  总体代码如此

 

转载于:https://www.cnblogs.com/ZyCoder/p/6696464.html

你可能感兴趣的文章
HTML-参考手册: 画布
查看>>
杂项:MIS
查看>>
Node.js:全局对象
查看>>
6、python中的字符串
查看>>
String、StringBuffer与StringBuilder之间区别
查看>>
bash中常见环境变量env、set、export 、declare与bash漏洞原理
查看>>
Vue.js 子组件的异步加载及其生命周期控制
查看>>
数据库表结构导出sql语句
查看>>
C++库(Thrift)
查看>>
第十五周助教小结
查看>>
P2260 [清华集训2012]模积和
查看>>
MD5加密工具类
查看>>
linux less命令详情
查看>>
Java框架之Mybatis(二)
查看>>
angular复选框式js树形菜单(二)
查看>>
java基础(第三章课后作业)04
查看>>
自定义ClassLoader
查看>>
用python发邮件实例
查看>>
Python基础-包
查看>>
oss文件删除策略
查看>>