表达式分为中缀表达式,后缀表达式和前缀表达式。
前缀表达式又叫波兰式,而后缀表达式又叫逆波兰式,因为一开始研究这个的是个波兰数学家。
其中,我们最熟悉的就是中缀表达式。如下:
(15-2)*3+4/2
表达式分为三个部分,操作数、运算符和界限符。
操作数就是上面的数字,运算符就是加减乘除一类的运算符号,界限符就是我们熟悉的大括号、中括号和小括号。
实际上,界限符是决定运算顺序的符号。
对于五加三,三种表达式有三种不同的表达方式,而结果其实并没有变化。
中缀表达式就是运算符号置于两个操作数之间,如5+3。
而后缀表达式就是将运算符置于两个操作数之后,如 5 3+。
那么前缀表达式就是将运算符置于两个操作数之前,如 +5 3。
注意:这里数字的顺序是不能改变的,尤其对于-*/这三种运算符,这和5-3跟3-5不同是一样的道理。
对于上面的5相同的地位的数称为前操作数,对于上面的3相同的地位的数称为后操作数。
我们知道一个表达式最终目的是化为一个操作数,因此,我们就可以在复合表达式中,将某个部分表达式视为一个操作数。
比如说(15-2)*3+4/2,我们就可以将(15-2)*3当成一个操作数去对待,而不用管表达式里面如何如何复杂。
(1)将中缀表达式转换为后缀表达式
举个例子:
(15-2)*3+4/2将这个中缀表示式化为后缀表达式。
我们先确定运算的顺序,如下:
第一步:15 2 -,我们将这个部分表达式视为一个操作数,进行下一步。
第二步: 15 2 - 3 *,操作数顺序不能颠倒。
第三步: 15 2 - 3 * 4 2 /,这里又增加了一个‘操作数’,进行下一步。
第四步: 15 2 - 3 * 4 2 / +,最终的到的式子就是后缀表达式。
其实,有的中缀表达式,不止一个运算顺序,因此,也就有不同的后缀表达式相对应。
如:15/5*3+5-2
我们既可以先算乘法,再算除法,也可以先算除法,再算乘法。
在乘除运算之后,我们既可以先算加法,也可以先算减法。
对于算法来说,算法具有确定性,因此计算机一般转换时都是按‘左优先’算法转换的,即假如运算符的优先级相同,比如*和/这两种运算符,则先从左边开始转化。
也就是说能先从左边开始,就从左边开始。
这样求得的后缀表达式就是唯一的,也可以看到上面我们求后缀表达式的式子,原本的运算顺序为1243,转换为后缀biao'da'shi后为1234。
上面都是手算,下面来看代码:
代码在最后。
(2)后缀表达式的计算
对于上面我们求出的算数表达式,如果我们想要计算,我们观察这个式子,很快就能相处计算方法。
方法如下:
比如说:上面我们求后缀表达式的中缀表达式式子为(15-2)*3+4/2,经计算为41。
后缀表达式为15 2 - 3 * 4 2 / +
我们采用后缀表达式的计算方法计算一遍。
第一次遇到运算符为‘-’,那么得到15-2=13。
第二次遇到运算符为‘*’,那么得到13*3=39。
第三次遇到运算符为‘/’,那么得到4/2=2。
第四次遇到运算符为‘+’,那么得到39+2=41。
完全和中缀表达式计算得到的结果相同。上面的方法对于哪一种后缀表达式都是适用的。
有了这种思想其实前缀表达式,同样的自己也就可以解决了。
(3)将中缀表达式转换为前缀表达式
举个例子:
(15-2)*3+4/2将这个中缀表示式化为前缀表达式。
我们先确定运算的顺序,如下:
第一步:/ 4 2,这里的表达式又是一个操作数。
第二步:- 15 2 / 4 2,操作数顺序不能颠倒。
第三步:* - 15 2 3 / 4 2
第四步:+ * - 15 2 3 / 4 2,最终的到的式子就是前缀表达式。
同理,算法具有确定性,因此,规定‘右优先‘,最后将运算的顺序2341转化后为4321。
操作3和4可以自己试着模仿1和2写代码,因此就不给代码了。
(4)前缀表达式的计算
对于上面我们求出的算数表达式,如果我们想要计算,我们观察这个式子,很快就能相处计算方法。
它和后缀表达式的计算方法顺序相反,如下:
举个例子: 计算上面求得的前缀表达式+ * - 15 2 3 / 4 2
从右向左:
第一次遇到运算符’/‘,得到4/2=2。
第二次遇到运算符’-‘,得到15-2=13
第三次遇到运算符’*‘,得到13*3=39
第四次遇到运算符’+‘,得到39+2=41
因此,41就是该前缀表达式的值。
(5)中缀表达式的计算
其实,对于中缀表达式,人是非常好计算的。但对于计算机而言,中缀表达式的计算方法是非常复杂的。
这就需要先将中缀转前缀或者后缀,然后按转换后的表达式的计算方法计算。
代码在最后。
//expression.h
#pragma once
#include
#include
class expression
{
public:
std::string inExpression;//中缀表达式
std::string poExpression;//后缀表达式
std::string prExpression;//前缀表达式
expression(std::string obj);
~expression(){};
int priority(char op);//运算符的优先级
bool isOp(char op);//是否是四种运算符号
std::string readInNum(int &i);//读取中缀表达式中数字
std::string readPoNum(int &i);//读取后缀表达式中数字
void inToPo();//中缀转后缀
void inToPr();//中缀转前缀
int answer();//表达式结果
};
//expression.cpp
#include "expression.h"
expression::expression(std::string obj)
{
inExpression = obj;
}
bool expression::isOp(char op)
{
if (op == '+' || op == '-' || op == '*' || op == '/')
return true;
return false;
}
int expression::priority(char op)
{
switch (op)
{
case '+':
case '-':return 0;
case '*':
case '/':return 1;
default:
break;
}
return -1;
}
std::string expression::readInNum(int &i)
{
std::string num;
while (isdigit(inExpression[i]))
{
num += inExpression[i];
i++;
}
i--;
return num;
}
std::string expression::readPoNum(int& i)
{
std::string num;
while (isdigit(poExpression[i]))
{
num += poExpression[i];
i++;
}
i--;
return num;
}
void expression::inToPo()
{
//(15-2)*3+4/2
//h
//po
std::stack h;
for (int i = 0; i < inExpression.size(); i++)
{
if (isdigit(inExpression[i]))
{
poExpression += readInNum(i);
poExpression += ' ';
}
else if (inExpression[i] == '(')
h.push(inExpression[i]);
else if (inExpression[i] == ')')
{
while (h.top() != '(')
{
poExpression += h.top();
poExpression += ' ';
h.pop();
}
h.pop();
}
else if (isOp(inExpression[i]))
{
//因为栈顶一定是优先级最高的,每次只需要和栈顶元素比较就行
while (!h.empty() && priority(inExpression[i]) < priority(h.top()))
{
poExpression += h.top();
poExpression += ' ';
h.pop();
}
h.push(inExpression[i]);
}
}
while (!h.empty())
{
poExpression += h.top();
poExpression += ' ';
h.pop();
}
}
void expression::inToPr()
{
}
int cal(int lhs, int rhs,char op)
{
switch (op)
{
case '+':return lhs + rhs;
case '-':return lhs - rhs;
case '*':return lhs * rhs;
case '/':return lhs / rhs;
default:
break;
}
return 0;
}
int expression::answer()
{
std::stacknum;
for (int i = 0; i < poExpression.size(); i++)
{
if (isdigit(poExpression[i]))
num.push(std::stoi(readPoNum(i)));
else if (poExpression[i] == ' ')
continue;
else if (isOp(poExpression[i]))
{
int rhs = num.top();
num.pop();
int lhs = num.top();
num.pop();
num.push(cal(lhs, rhs, poExpression[i]));
}
}
return num.top();
}