数据结构学习实录三—中缀表达式转后缀表达式(C++)

来源:互联网 发布:ubuntu install kde 编辑:程序博客网 时间:2024/05/16 23:53

精力几欲透支,一天写三篇计算机博文不是盖的,废话不多说,老夫还有一口气,上!

栈大家都懂了吧,此物想来也不难,老夫今日几欲吐血,就不详细介绍了,不会的男同学百度,女同学私聊。

那么栈是非常有用的一种数据结构思想,尤其在其解决迷宫问题时显现出难以替代的优越性,并且在解决中缀表达式转后缀表达式中也意义重大。

什么是中缀表达式?

你从小就写,普通的算式就是中缀表达式,比如A+B*(C-D)-E/F;简单吧,见过吧,自己写过无数遍了吧。那么,我们知道,这种表达式是为了计算数字,人类操作和计算非常方便,但是计算机不同,计算机可不喜欢这种表达式,他没有那么复杂的直接运算,他希望能够使用后缀表达式。那么上面的式子转成后缀表达式是什么样的呢?

ABCD-*+EF/-;稀奇吧,古怪吧,没见过吧,那就对啦!嘿嘿,怎么算?看老夫娓娓道来。

你从前往后读,ABCD减号!看见运算符了吧,把运算符前面两个数字拿出来,C和D,好,把减号放中间,C-D,成功了,然后把CD-换成C-D,C-D当整体看就是AB(C-D)*+EF/-;

同样从前往后看,C-D已经是一个数字了啊,当整体看。A B (C-D) 乘号!取乘号前两个数字 B (C-D),乘号放中间,成B*(C-D),然后把B*(C-D)当成整体放回,变成AB*(C-D)+EF/-;

然后,再从前往后看AB*(C-D)加号!取运算符前两个数字,A和B*(C-D);变成A+B*(C-D);继续,A+B*(C-D)EF除号!取运算符前两个数字E和F,加上除号变成E/F,放回变成A+B*(C-D)E/F继续读;A+B*(C-D)E/F减号!取运算符前两个数字,A+B*(C-D)和E/F,换上减号,成A+B*(C-D)-E/F;是不是和中缀表达式一样了。那么这么做有什么意义呢?

我们先来看下中缀表达式的计算法则:

1.有括号要先算括号里的。

2.乘除比加减优先级要高。

3.乘方与开方比乘除优先级要高。

4.计算顺序根据题目自行确定。

中缀表达式不能使用较为简单的逻辑进行描述,所以如果使用中缀表达式进行运算,编程实现无疑是困难了许多。

我们分析下,后缀表达式的运算法则非常简单

1.从前往后扫描,数字不做处理。

2.遇到运算符,则取运算符前两个数字进行计算。

3.用计算结果替代原来两个数字和运算符,并从新从第一步开始运行,直到只有一个数字为止。

我们可以看到,这样的话,一个复杂表达式的计算就被转成循环和简单条件的判定了,非常利于编程实现。

那么我们讨论下,中缀表达式如何转后缀表达式呢?

其实我们可以使用二元树进行后续遍历实现,不过由于还没有学到树,并且实现很简单就先留给读者自行解决了,以后我再做讲解。

在此我们使用栈对+-*/()进行实现,其他的运算符暂不实现。

额  讲解好难  怎么讲?

首先  我们对所有运算符加上优先级判定。且优先级分为内优先和外优先

优先级操作符#()*, /+, -内优先isp01653外优先icp06142
然后呢,我们在表达式前后加上‘#’作为标注,比如 A+B*(C-D)-E/F;就会变成#A+B*(C-D)-E/F#,方便判断。

首先讲解规则

1.生成栈区,用于临时存放运算符。

2.遇到数字,直接输出到后缀表达式。

3.当栈为空时,运算符或‘#’直接进栈

4.遇到运算符,若栈顶元素的内优先数小于遇到运算符的外优先数,则允许外运算符入栈(压栈);若栈顶元素的内优先数大于遇到运算符的外优先数,则将栈顶运算符输出(出栈),再将外运算符进行第四步判断。括号也算运算符。若栈顶元素的内优先数等于遇到运算符的外优先数,则将栈顶运算符弹出,两个运算符直接丢弃,不做输出。

四条基本规则解释完毕,接下来编程实现。

为了程序便于移植,主函数不做过多操作,仅用于数据传输。

// 中缀表达式转后缀表达式.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include"iostream"using namespace std;typedef struct SqStack{char date[30];int top=0;}SqStack;//用于确定符号的优先级 i=true代表内优先,否则为外优先,返回值为-1时,代表是数字。int mynum(char a, bool i){if (a == '#')return 0;if (a == '(')if (i == true)return 1;elsereturn 6;if (a == ')')if (i == true)return 6;elsereturn 1;if (a == '*'||a=='/')if (i == true)return 5;elsereturn 4;if (a == '+' || a == '-')if (i == true)return 3;elsereturn 2;return -1;}//对栈进行操作的函数void transform(char* oldl, char* inew){int num = 0,inum=0,n=0;SqStack a;//生成栈区char old[30];//对表达式前后加#old[0] = '#';int ii = 0;for (ii = 0; oldl[ii] != '\0'; ii++){old[ii + 1] = oldl[ii];}old[ii+1] = '#';old[ii + 2] = '\0';//加#结束for (int i = 0; i < 30; i++){a.date[i] = 0;}//栈区清空a.date[a.top] = '#';//首#入栈//对表达式进行转换for (int i = 1; old[i] != '\0'; i++){num = mynum(old[i], 0);if (num != -1){inum = mynum(a.date[a.top], 1);if (num > inum){a.top++;a.date[a.top] = old[i];}else if (num == inum){a.date[a.top] = 0;a.top--;}else{inew[n] = a.date[a.top];n++;a.top--;i--;}}else{inew[n] = old[i];n++;}}inew[n] = '\0';}int main(){char s[30] = "A+B*(C-D)-E/F";char ss[30];transform(s, ss);cout << ss;system("pause");    return 0;}




本文为作者原创,任何形式的引用、转载等操作请提前获得作者授权,未经授权,禁止以任何形式引用或转载此文。