中缀运算符方法的名称

1358:中缀表达式值(expr) 题目描述】输入一个中缀表达式(由0-9组成的运算数、加+减-乘*除/四种运算符、左右小括号组成。注意“-”也可作为负数的标志,表达式以“@”作为结束符),判断表达式是否合法,如果不合法,请输出“NO”;否则请把表达式转换成后缀形式,再求出后缀表达式的值并输出。注意:必须用栈操作,不能直接输出表达式的值。【输入】一行为一个以@结束的字符串。【输出】如果表达式不合法,请输出“NO”,要求大写。如果表达式合法,请输出计算结果。【输入样例】1+2*8-9@【输出样例】8。... 阅读详情

 

中缀运算符方法的名称

 

“计算中缀表达式”可以称得上是一个特别经典的关于栈的算法题,几乎在所有数据结构教材中都会涉及,而且很多公司面试或者笔试的时候都会把这道题作为一个考察点。可以说,这是一道必须要掌握的算法题。中缀表达式、后缀表达式等概念在这里就不赘述了,让我们直奔主题。

题目:输入一个中缀表达式,计算其结果。

输入的前提假设:

(1)只考虑+、-、*、/这四种运算符,中缀表达式中只有一种括号:();

(2)输入的中缀表达式中只有整数,没有小数;

(3)假定输入是合法的。

很多文章或课本喜欢一步到位,直接讨论如何从中缀表达式计算结果。但对于初学者来说,跨度未免大了点。这里循序渐进,从易到难,先讨论如何将中缀表达式转化为后缀表达式,再讨论如何计算后缀表达式。最后在前面两步的基础上,讨论如何一步到位,直接计算中缀表达式的结果:

一、如何将中缀表达式转化为后缀表达式

在日常应用中,算术表达式中运算符总是出现在两个操作数之间,例如5*(7-2*3)+8/2,这种形式称为中缀表达式。计算一个中缀表达式需要知道运算符的优先级和结合性。乘除是高优先级,加减是低优先级,优先级相同时他们都是左结合的,也就是从左计算到右。有括号就要计算括号内的表达式。

中缀表达式利于人的理解,但不便于计算机的处理。因此需要将中缀表达式转换成后缀表达式,以方便计算机处理。所谓后缀表达式就是将运算符放在运算数之后。后缀表达式也称为逆波兰表达式。

比如:

中缀表达式为:1+(2-3)*4+4/2

对应后缀表达式为:1 2 3 - 4* + 4 2 / +

如何将一个中缀表达式转化为后缀表达式?我们需要借助栈的力量,用它来存放运算符。算法流程如下:

首先将各种运算符(包括括号)的优先级排列如下(数字越大,优先级越高):

1:(

2:+ -

3:* /

4:)

对输入的中缀表达式从左到右遍历:

1)如果遇到数字,直接添加到后缀表达式末尾;

2)如果遇到运算符+、-、*、/:

先判断栈是否为空。若是,则直接将此运算符压入栈。若不是,则查看当前栈顶元素。若栈顶元素优先级大于或等于此操作符级别,则弹出栈顶元素,将栈顶元素添加到后缀表达式中,并继续进行上述判断。如果不满足上述判断或者栈为空,将这个运算符入栈。要注意的是,经过上述步骤,这个运算符最终一定会入栈。

3)如果遇到括号:

如果是左括号,直接入栈。如果是右括号,弹出栈中第一个左括号前所有的操作符,并将左括号弹出。(右括号别入栈)。

4)字符串遍历结束后,如果栈不为空,则弹出栈中所有元素,将它们添加到后缀表达式的末尾,直到栈为空。

二、计算后缀表达式

后缀表达式的计算就相当简单了。准备一个数字栈。从左到右扫描后缀表达式,如果是数字,放入数字栈。如果是符号,从数字栈中弹出两个数字,第一个取出的数字为右运算数,第二个为左运算数,进行运算。然后将结果放进数字栈中。如此反复,直到读完整个表达式后,留在数字栈中的那个数字就是最终结果。

C++代码如下,要注意,下面的代码默认中缀表达式中所有数字都是整数,并且都在0到9之间。而且计算结果都是整数(比如5/2=2)。

[cpp] view plain copy

  1. #include<iostream>  
  2. #include<string>  
  3. #include<stack>  
  4.   
  5. using namespace std;  
  6.   
  7. int getPriority(char ch)  
  8. {  
  9.     //获取优先级  
  10.     if (ch == '(') return 1;  
  11.     else if (ch == '+' || ch == '-') return 2;  
  12.     else if (ch == '*' || ch == '/') return 3;  
  13.     else return 4;  
  14. }  
  15.   
  16. string getPostfixExpression(string str)  
  17. {  
  18.     //将中缀表达式转化为后缀表达式  
  19.     //默认输入是合法的  
  20.     stack<char> mystack;  
  21.     int size = str.size();  
  22.     int i = 0;  
  23.     char tmp;  
  24.     string res = "";  
  25.     while (i < size) {  
  26.         if (str[i] >= '0' && str[i] <= '9'){  
  27.             res.push_back(str[i]);  
  28.         }  
  29.         elseif (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {  
  30.             if (mystack.empty()) {  
  31.                 mystack.push(str[i]);  
  32.             }  
  33.             else {  
  34.                 while (!mystack.empty()) {  
  35.                     tmp = mystack.top();  
  36.                     if (getPriority(tmp) >= getPriority(str[i])) {  
  37.                         //弹出栈顶元素  
  38.                         res.push_back(tmp);  
  39.                         mystack.pop();  
  40.                     }  
  41.                     else break;  
  42.                 }  
  43.                 mystack.push(str[i]);  
  44.             }  
  45.         }  
  46.         else {  
  47.             if(str[i]=='(') mystack.push(str[i]);  
  48.             else {  
  49.                 while (mystack.top() != '(') {  
  50.                     tmp = mystack.top();  
  51.                     res.push_back(tmp);  
  52.                     mystack.pop();  
  53.                 }  
  54.                 mystack.pop();  
  55.             }  
  56.         }  
  57.         i++;  
  58.     }  
  59.   
  60.     //遍历完后,若栈非空,弹出所有元素  
  61.     while (!mystack.empty()) {  
  62.         tmp = mystack.top();  
  63.         res.push_back(tmp);  
  64.         mystack.pop();  
  65.     }  
  66.     return res;  
  67. }  
  68.   
  69.    
  70.   
  71. int calculator(string str)  
  72. {  
  73.     //计算后缀表达式的值,默认中缀表达式所有数字都是一位的,在0-9之间  
  74.     stack<int> mystack;  
  75.     int size = str.size();  
  76.     int num1, num2, num3;  
  77.     for (int i = 0; i < size; i++) {  
  78.         if (str[i] >= '0' && str[i] <= '9') {  
  79.             mystack.push(str[i] - '0');  
  80.         }  
  81.         else {  
  82.             num2 = mystack.top();  
  83.             mystack.pop();  
  84.             num1 = mystack.top();  
  85.             mystack.pop();  
  86.             if (str[i] == '+') {  
  87.                 num3 = num1 + num2;  
  88.             }  
  89.             else if (str[i] == '-') {  
  90.                 num3 = num1 - num2;  
  91.             }  
  92.             else if (str[i] == '*') {  
  93.                 num3 = num1 * num2;  
  94.             }  
  95.             else if (str[i] == '/') {  
  96.                 num3 = num1 / num2;  
  97.             }  
  98.             mystack.push(num3);  
  99.         }  
  100.     }  
  101.     return mystack.top();  
  102. }  
  103.   
  104.    
  105. int main()  
  106. {  
  107.     string str="1+(2-3)*4+4/2";  
  108.     cout <<"中缀表达式为:"<< endl << str << endl;  
  109.     string res = getPostfixExpression(str);  
  110.     cout <<"后缀表达式为:"<< endl << res << endl;  
  111.     int num_res = calculator(res);  
  112.     cout <<"计算结果:"<< endl << num_res << endl;  
  113.     system("pause");  
  114.     return 0;  
  115. }  

三、直接计算中缀表达式

其实将前面的两步结合起来,就可以得到直接计算的方法。准备一个数字栈和一个符号栈。

从左到右遍历中缀表达式。如果遇到数字,入数字栈。

如果遇到符号(四个运算符以及括号),跟前面的“中缀表达式转后缀表达式”过程一样,对符号栈进行处理。处理过程中,对每一个出栈的运算符:+ - * /,根据“计算后缀表达式”的方法,计算结果(跟数字栈配合)。

如果遍历完中缀表达式后符号栈还非空,就继续出符号栈的运算符,计算,直到符号栈为空。最后数字栈剩下的数字就是结果。

下面给出用C++实现“计算中缀表达式”的代码,里面考虑了“数字不止1位”,并且用浮点型来表示最终运算结果。要求中缀表达式中只能包含整数和运算符(不能包含小数),并且是合法的。

[cpp] view plain copy

  1. #include<iostream>  
  2. #include<string>  
  3. #include<stack>  
  4.   
  5. using namespace std;  
  6.   
  7. int getPriority(char ch)  
  8. {  
  9.     //获取优先级  
  10.     if (ch == '(') return 1;  
  11.     else if (ch == '+' || ch == '-') return 2;  
  12.     else if (ch == '*' || ch == '/') return 3;  
  13.     else return 4;  
  14. }  
  15.   
  16. void calculate(stack<double> &mystack, char operation)  
  17. {  
  18.     double num1, num2, num3;  
  19.     num2 = mystack.top();  
  20.     mystack.pop();  
  21.     num1 = mystack.top();  
  22.     mystack.pop();  
  23.     if (operation == '+') {  
  24.         num3 = num1 + num2;  
  25.     }  
  26.     else if (operation == '-') {  
  27.         num3 = num1 - num2;  
  28.     }  
  29.     else if (operation == '*') {  
  30.         num3 = num1 * num2;  
  31.     }  
  32.     else if (operation == '/') {  
  33.         num3 = num1 / num2;  
  34.     }  
  35.   
  36.     mystack.push(num3);  
  37. }  
  38.   
  39. double calculator(string str)  
  40. {  
  41.     //计算中缀表达式,默认输入是合法的  
  42.     stack<double> mystack_number;  
  43.     stack<char> mystack_operation;  
  44.     int i = 0, j;  
  45.     int size = str.size();  
  46.     char tmp_operation;  
  47.     string tmp_num;  
  48.     while (i < size) {  
  49.         if (str[i] >= '0' && str[i] <= '9') {  
  50.             j = i;  
  51.             while (j < size && str[j] >= '0' && str[j] <= '9') { j++; }  
  52.             tmp_num = str.substr(i, j - i);  
  53.             mystack_number.push(atoi(tmp_num.c_str()));  
  54.             i = j;  
  55.         }  
  56.         else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {  
  57.             if (mystack_operation.empty()) {  
  58.                 mystack_operation.push(str[i]);  
  59.             }  
  60.             else {  
  61.                 while (!mystack_operation.empty()) {  
  62.                     tmp_operation = mystack_operation.top();  
  63.                     if (getPriority(tmp_operation) >= getPriority(str[i])) {  
  64.                         //计算  
  65.                         calculate(mystack_number, tmp_operation);  
  66.                         mystack_operation.pop();  
  67.                     }  
  68.                     else break;  
  69.                 }  
  70.                 mystack_operation.push(str[i]);  
  71.             }  
  72.             i++;  
  73.         }  
  74.         else {  
  75.             if (str[i] == '(') mystack_operation.push(str[i]);  
  76.             else {  
  77.                 while (mystack_operation.top() != '(') {  
  78.                     tmp_operation = mystack_operation.top();  
  79.                     //计算  
  80.                     calculate(mystack_number, tmp_operation);  
  81.                     mystack_operation.pop();  
  82.                 }  
  83.                 mystack_operation.pop();  
  84.             }  
  85.             i++;  
  86.         }  
  87.   
  88.     }  
  89.     //遍历完后,若栈非空,弹出所有元素  
  90.     while (!mystack_operation.empty()) {  
  91.         tmp_operation = mystack_operation.top();  
  92.         //计算  
  93.         calculate(mystack_number, tmp_operation);  
  94.         mystack_operation.pop();  
  95.     }  
  96.     return mystack_number.top();  
  97. }  
  98.   
  99. int main()  
  100. {  
  101.     string str = "1+(2-3)*4+10/2+2*2+2+2/5";  
  102.     cout << "中缀表达式为:" << endl << str << endl;  
  103.     double num_res = calculator(str);  
  104.     cout << "计算结果:" << endl << num_res << endl;  
  105.     system("pause");  
  106.     return 0;  
  107. }  

 

相信通过这篇文章,大家对这个问题会有所了解。

给出一道思考题:如果加入乘方'^',应该如何处理?要注意,乘方运算是右结合的。

其实很简单。只有两处修改:

1)将乘方添加到优先级中:

 

1:(

2:+ -

3:* /

4:^

5:)

2)在读中缀表达式的时候,如果读到乘方^,就将它放进符号栈中。因为乘方的优先级是最高的,而且是右结合的,所以无论它前面出现的是什么运算,这些运算都不能执行。而且它本身能否执行也是不知道的,因此只能进栈。

大家自己试试吧~要记住,学习编程,动手去写代码永远是第一位的。

【参考资料】

[1]https://blog.csdn.net/sinat_36118270/article/details/70257547

[2]翁惠玉, 俞勇. 数据结构:思想与实现[M]. 高等教育出版社, 2009.

编写一个用输入和输出流运算符进行的输入和输出的程序。从键盘输入两个数,分别对两个数进行加,减,乘和除的运算。 编写一个用输入和输出流运算符进行的输入和输出的程序。从键盘输入两个数,分别对两个数进行加,减,乘和除的运算。并输出计算结果,如: 23+123=146。 #include using namespace std; main() { float a,b,A,B,C,D; cout<<"请输入两个数(输完第一个数后按enter键再输第二个)"<>a>>b; A=a+b; B=a-b; C=a*b; D=a/b; cout<<"a+b="<<A<<endl; cout<<"a-b="<<B<<endl; cout<<"a*b="<<C<<endl; cout<<"a/b="<<D<<endl; } 立即下载

相关推荐

栈及其应用-中缀表达式转后缀表达式并用后缀表达式求值

栈及其应用-中缀表达式转后缀表达式并用后缀表达式求值 一:栈的基本原理 栈是一种特殊的线性表,因为它对线性表中的元素做出了明确的要求:栈中的元素只能从线性表的一端进出,且要遵循“先入后出”的原则,即先进栈的元素后出栈。 基于栈结构的特点,在实际应用中,通常会对栈执行以下两种操作: 向栈中添加元素,此过程被称为“进栈”(PUSH、入栈或压栈); 从栈中提取出指定元素,此过程被称为“出栈”(POP、或弹栈); 进栈和出栈一般采用数组和栈顶指针来实现栈。 进栈(PUSH)算法: ①:若top>=n,则给出

w1050321758的博客 1257

一本通1358:中缀表达式值(expr)

痛苦,好痛苦。。。

KINGtxy520的博客 1617

计算中缀表达式

“计算中缀表达式”可以称得上是一个特别经典的关于栈的算法题,几乎在所有数据结构教材中都会涉及,而且很多公司面试或者笔试的时候都会把这道题作为一个考察点。可以说,这是一道必须要掌握的算法题。中缀表达式、后缀表达式等概念在这里就不赘述了,让我们直奔主题。题目:输入一个中缀表达式,计算其结果。输入的前提假设:(1)只考虑+、-、*、/这四种运算符,中缀表达式中只有一种括号:();(2)输入的中缀表达式中...

凛冬烈焰的博客 7857

Fluent Python - Part13 正确重载运算符

运算符重载的作用是让用户定义的对象使用中缀运算符(如 + 和 |) 或一元运算符(如 - 和 ~)。说的宽泛一些,在 Python 中,函数调用(()),属性访问(.)和元素访问/切片([]) 也是运算符,不过本章只讨论一元运算符和中缀运算符。 在接下来的几节,我们将讨论: Python 如何处理中缀运算符中不同类型的操作数 使用鸭子类型或显式类型检查处理不同类型的操作数 中缀运算符如何表明自己无法处理操作数 众多比较运算符(如 ==, >, <=, 等等) 的特殊行为 增量赋值运算符(如 +

qq_34921856的博客 224

再谈扩展方法,从string.IsNullOrEmpty()说起

string.IsNullOrEmpty()这个方法算得上是.net中使用频率最高的方法之一。此方法是string的一个静态方法,类似的静态方法在string这个类中还有很多。那么这样的方法作为静态方法是否合理呢?如果我们从面向对象的角度出发,我们会发现这种方案不是十分符合面向对象的设计原则。 什么是对象?对象是拥有数据和行为的结合体。如果说string是一个类,那么string message...

weixin_34297300的博客 528

Elm学习指南

Elm基础语法 常用数据结构 列表List : 只能容纳单一类型元素,是类型的容器而不是类型,List String才是类型 元祖Tuples:可为不同类型,固定长度小于10 Records : 具有键值对的数据结构 List (列表) list 方法 List.drop 1 [1,2,3,4] — [1,2,3] List.length [1,2,3,4] — 4 List.head...

weixin_34061042的博客 294

数组-操作数组两端的特殊方法

如果要从数组的开头添加一个元素,需要使用unshift方法,在下面操作之后 a=[1,2,3,4] a.unshift(0) 数组看起来是这样的:[0,1,2,3,4] 如果要在数组的末尾添加一个对象,可以使用push方法。具体如下 a=[1,2,3,4] a.push(5) 这样既可以得到5个元素的数组[1,2,3,4,5].也可以使用&l...

fd2015的博客 151

Scala3运算符规则深度解析:从基础到最佳实践

Scala3运算符规则深度解析:从基础到最佳实践 前言 Scala作为一门融合面向对象和函数式编程特性的语言,其运算符系统一直是非常灵活且强大的特性。在Scala3中,对运算符的使用规则进行了多项重要改进,这些变化不仅提升了代码的一致性,也增强了可读性和互操作性。本文将全面解析Scala3中的运算符新规则。 中缀运算符的infix修饰符 基本概念 在Scala3中,字母数字方法(alphanume...

gitblog_00844的博客 456

如何查看功能的源代码?

I want to look at the source code for a function to see how it works. 我想查看功能的源代码以了解其工作原理。 I know I

asdfgh0077的博客 1786

kotlin: ::符号_Kotlin月刊1:各种功能

kotlin: ::符号 要打开“ Kotlin月”,我们将查看Kotlin的一小部分功能,这些功能不足以值得自己写文章,也不适合将要发布的文章归类,从操作员重载开始。 运算符重载 由于它在C ++中造成的混乱,Java决定不包括运算符重载 ,并且不幸的是,它坚持了这一决定,大概是因为人们对此没有足够的恶臭。 如果大多数Java程序员对这种语言没有太多/任何经验,这是有道理的,我认为目前可...

248

Kotlin月刊1:各种功能

要打开“ Kotlin月”,我们将研究Kotlin的一小部分功能,这些功能不足以胜任自己的帖子,并且不适合即将发布的帖子进行分组,从操作员重载开始。 操作员超载 由于它在C ++中造成的混乱,Java决定不包括运算符重载 ,并且不幸的是,它坚持了这一决定,大概是因为人们对此还没有足够的恶臭。 如果大多数Java程序员对这种语言没有太多/任何经验,这是有道理的,我认为目前可能是这种情况。 ...

108

《Composing Programs》学习笔记(1.3)定义新函数(关键词:软件工程/函数)

1.3 Defining New Functions 1.3 定义新函数 Video: Show Hide 视频:Show Hide We have identified(识别;确定) in Python some of the elements that must appear in any powerful programming language: 我们已经确定,在Python

Henry1991back的博客 1329

《零基础入门CS61A!Lecture 3》

我们在当前环境中找到该名称的最早框架(check f2 first)可以通过在特定的文件调用文档测试模块来运行的。和==floordiv ==函数的简写。

2301_79317978的博客 609

python特殊方法的重要用途

有几种特殊方法可以使用户对象响应+、*等运算符,接下来通过实现一个二维向量类来对此进行说明。一个简单的二维向量应实现向量加法、计算向量的模、向量的标量积的运算示例使用了__repr__、__abs__、__add__、__mul__等特殊方法为Vector类实现了上述的运算。其中__add__、__mul__这两个方法创建并返回一个新的Vector实例,没有修改运算对象,只是读取self、other,这是中缀运算符的预期行为,即创建新对象,不修改运算对象。

m0_69298614的博客 798

scala:类型推断、操作符

Scala可以自行推导表达式类型,所以不需要进行显式声明。 1 忽略类型 # 自动推导变量类型 val uio = "teset" # 自动推导方法返回值类型 def fff(x:Int)=x * x # 推导返回值类型失败(编译器无法推导递归定方法的返回值类型,需要显式声明) def fac(n:Int) = if(n == 0) 1 else n * fac(n - 1) # 推导...

不花的花和尚的博客 364

Python 正确重载运算符(重载标量乘法运算符_)

因此,不能使用复数,但可以是int、bool(int 的子类),甚至 fractions.Fraction 实例等标量。积(scalar product),结果是一个新 Vector 实例,各个分量都会乘以。❷ 如果 scalar 是 numbers.Real 某个子类的实例,用分量的乘积创建。0465/),提供了点积所需的 @ 记号(例如,a @ b 是 a 和 b 的点。为了体验一下,我从源码编译了 Python 3.5,然后为 Vector 实现了。不过,写作本书时,Python。

钢铁男儿 730
上一篇: python中切片split()函数用法
下一篇: 用Python实现中文编程
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值