定义
- 中缀表达式:平常我们手动输入的表达式、计算式,都是中缀表达式,按照我们理解的运算优先顺序进行计算。按照人的思维方式进行表达式的输入,最终输出预期结果。比如 1 + (2 + 3) × 4 - 5
- 后缀表达式、前缀表达式:虽然中缀表达式是按照我们肉眼的运算符优先级写出的,但是最终实现这个运算的,比如计算器是没有这么智能的,计算器只会按照输入的运算符一个一个的进行计算。这时候就用到了后缀、前缀表达式。比如:后缀表达式针对于上面的就是 1 2 3 + 4 × + 5 -
手动实现
-
那么我们怎么实现中缀转换为后缀呢?
手动实现:把所有运算按照优先级加上括号,然后把运算符号移动到括号前面,然后去除括号。
比如:1 + (2 + 3) × 4 - 5
加括号:
1 +( (2 + 3) × 4 ) - 5
(1 +( (2 + 3) × 4 )) - 5
((1 +( (2 + 3) × 4 )) - 5)
运算符号后移,并去除括号:
1 2 3 + 4 × + 5 -
前缀表达式,就是符号前移,一样的
2.计算机怎么去识别后缀呢
使用大名鼎鼎的栈就很方便的实现了
栈的特点是先进后出,后进先出
针对于后缀表达式
1. 遇到数字入栈
2. 遇到运算符,弹出栈的两个数字,然后和运算符进行运算
3. 重复过程
4. 因为后缀表达式,其实已经是把运算符优先级顺序换一种表示形式,展现出来了而已
程序实现
说了一大推,我们首先来看一下程序上的实现一个对中缀表达式进行输入,然后进行转换,并进行结果的输出
步骤
1. 中缀表达式转化为后缀表达式
2. 进行后缀表达式的计算
第一步
程序思路:
-
定义栈S1,存储运算符。定义栈S2,存储数字和运算符,存储最终的后缀表达式
-
对于新字符进行判断只要新字符不等于‘\0’,一直进行下面的循环:
-
如果S1的大小为空, 字符入S1
-
如果是( 入栈
-
如果是),将S1知道(之前的运算符出栈,添加到S2中
-
如果S1的大小不为空,并且S1栈顶的运算符优先级大于当前的新字符或者两个字符是相等的
那么当前的S1栈顶就可以出栈,添加到S2中
新字符入栈S1
-
如果新字符的范围是‘0’ - ’9‘之间,那么新字符添加进S2中
-
否则,添加到S1中
-
-
跳出循环后,如果S1的size不为空,把S1的运算符一一弹出,添加到S2中,最终S2就是排列好的后缀表达式
-
然后就可以进行运算
代码,使用c++
int weight(const char code) { if((code == '+') || (code == '-')) { return 1; } else if((code == '*') || (code == '/')) { return 2; } } bool priority(const char left, const char right) { if(left == '(') { return false; } else if(weight(left) < weight(right)) { return false; } else { return true; } } bool caculation(const char* input, LinkStack<char>& S2) { if(input == NULL) { return false; } bool ret = true; LinkStack<char> S1; int i = 0; int out_index = 0; while(ret && (input[i] != '\0')) { if(input[i] == '(') { S1.push(input[i]); } else if((S1.size() > 0) && (input[i] == ')')) { char code = S1.get(); while(code != '(') { S2.push(code); S1.pop(); code = S1.get(); } if(code == '(') { S1.pop(); } } else if((S1.size() > 0) && priority(S1.get(), input[i])) { std::cout << "13" << std::endl; char code = S1.get(); S2.push(code); S1.pop(); S1.push(input[i]); } else if( (input[i] >= '0') && (input[i] <= '9')) { S2.push(input[i]); } else { S1.push(input[i]); } i++; } while(S1.size() > 0) { char code = S1.get(); S2.push(code); S1.pop(); } return ret; }
- 核心函数就是上面的两个,输入参数1是中缀表达式,输入参数2是栈,最终栈中存储排序好的后缀表达式
- 拿一个例子来演示一下:
6.
说明
后缀表达式,这种方式后计算优点也很大,直接从上到下,数字就入栈,符号就把当前栈中的连续两个弹出,然后和当前符号进行运算,然后再入数字栈。