本来把这个表达式求值只是我们一次数据结构的简单实验但是把,刚开在脑子里构思的时候好好的
但是把每当自己亲手动手实验时你就会发现原来我有这么多的细节没有想到。所以说嘛,不能只停
留在思考和看懂的层面,你不动手实践的话你永远不知道你到底掌握到生么程度了。
实验目的:1:加深对线性表的熟练度
2:掌握栈和对列的基本操作
实验原理: 1:四则运算规则:先乘除 后 加减,有括号先算括号里面的。
2:运算符之间的优先关系这个运算符之间的优先级关系,最开始我是觉得这个图没有什么好讲的但是由于我在上课时看到我们班的同学有很多看不懂这个图问老师老师他也不知道怎么解释,于是我就在这里解释一下吧!
我看了很多的博客他们都没有讲怎么看这个优先级关系图这里面把
我就拿我们本次的实验来说 上面不是有θ1和θ2吗看的方式是从左向右看 其中就拿第一个大于号
来说(就是第一行第一列中+所对应的)可以看作是θ1加号的优先级>θ2加号的优先级 这个解释过
后就拿我们的实验来说 因为我们本实验是需要创建两个栈的一个是符栈(用来存取字符的)一个
是数栈(用来存取数据和计算结果)
那么第一种理解方式:
我们就可以把θ1当作是符栈中的字符而。
把θ2当作是我们输入的表达式中的字符。
即一个是栈中的字符另一个是未入栈的字符。
第二种理解方式:
我们可以找到两个相连的字符。
把前面的那个当作θ1 后面的θ2来使用 进行比较。
我这我们本实验重难点的理解。
但是把 我这次写的代码没有使用这个图但是原理是相通的!
我相信你能看懂这个图之后也一定能看懂我的代码!
编写代码思路:我们这个实验由于是和栈相关的实验,所以嘛!我们肯定会用到栈的相关操作,我们就这分析就会发现本实验我们需要两个栈 符栈 和 数栈 那么我们首先就需要
1:创建两个结构体
结构体中一个用来存储初始化符栈另一个用来存储初始化(这里说的不太严谨哈!)数栈
经过分析我们还需要有栈的入栈,出栈,取栈值,初始化。
2:创建两个栈的初始化方法
两个初始化 一个用于初始化 符栈 另一个用于初始化 数栈
3:创建两个入栈方法
两个入栈方法 一个用于 符栈的入栈 另一个用于 数栈入栈
4:创建两个出栈方法
两个出栈方法 一个用于 符栈出栈 另一个用于 数栈出栈
5:创建两个取值方法
两个取值方法 一个用于 符栈取值 另一个用于 数栈求值
注:(出栈和取值的区别
出栈:取出原来的栈顶元素的值,并删除栈顶元素,由洗一个元素顶替
取值:只获取栈顶元素的值,而不删除栈顶元素的值)
6:创建一个判断字符优先级方法
7:创建运算具体实验的方法(即+,-,*,/)
8:创建一个总的操作方法用于实现表达式求值
9:创建主函数
实验过程:下面这张上图是借用我们上课用的ppt用来理解的 步骤和我的有那么一点点的不同但原理是一样的
下面这几个步骤图是借用网上的用来理解的 步骤和我的有那么一点点的不同但原理是一样的
步骤一:
步骤二:
步骤三:
步骤四:
步骤五:
步骤六:
步骤七:
步骤八:
步骤九:
步骤十:
实验的算法步骤:1:首先输入被求值的表达式,调用操作方法 既是上面的第八步
2:首先创建两个符型和数型的结构体对象 初始化两个结构体对象
3:使用for循环调用相关的方法把我们所输入的表达式进行入栈操作
a:我们使用for循环一个一个字符的进行判断 首先判断我们输入的字符是否是数字
若是数字直接入栈
b:若是字符的话我们会进行判断
当符栈为空 我们的字符会直接入栈
或者是满足栈中字符的优先级小于表达式字符中的优先级进行入栈
或者是遇到“(”这个字符我们也会直接入栈
c:当遇到栈中字符的优先级大于表达式字符中的优先级时我们需要进行的是
表达式的相关操作 然后把操作结果存入数栈中
此时我们不能忘记 现在我们这里进行判断的是表达式中的字符
我们还需要进行表达式中的字符进行入栈操作(必须是在在栈顶字符出站后)
d:最后判断符栈中是否还存有字符这里的话(造成有这一步的原因是 我们的在进行入栈时
遇见"("是直接入栈的 还有一个原因就是表达式中没有一个是与我们栈中最后一个字符进
行
比价的(这里就是有一些难理解,自己再好好想想理解理解))
你可以结合我的代码再看一下,我在其中个各个步骤都加入了详细的解释,加上我的代码的话因该是能更好的理解的
代码展示:#include效果展示:#include #define max 100 using namespace std; typedef struct stu1 //创建存储运算符的结构体 { char data[max]; int top; }stu1; typedef struct stu2 //创建存储数字的结构体 { int data[max]; int top; }stu2; //这里面是运算符的方法 stu1 *Init_stu1() //初始化运算符结构体 { stu1 *s; s=new stu1; if(!s) { exit(1); } s->top=-1; return s; } int Empty_stu1(stu1 *L) //判断运算符栈是否为空 { if(L->top==-1) { return 0; } else { return 1; } } int Push_stu1(stu1 *L,char a) //运算符 栈的入栈操作 { if(L->top==max-1) { return 0; } L->data[++L->top]=a; return 1; } char Pop_stu1(stu1 *L,char a) //运算符 出栈操作 { if(L->top==-1) { return 0; } else { a=L->data[L->top--]; } return a; } char GetTop_stu1(stu1 *L,char a) //运算符 取值操作 { if(L->top==-1) { return 0; } else { a=L->data[L->top]; } return a; } //这里是 操作数的方法 stu2 *Init_stu2() //操作数的初始化操作 { stu2 *s; s=new stu2; s->top=-1; return s; } int Empty_stu2(stu2 *L) //操作数的判空操作 { if(L->top==-1) { return 0; } else { return 1; } } int Push(stu2 *L,int a) //操作数的入栈操作 { if(L->top==(max-1)) { return 0; } else { L->data[++L->top]=a; } return 1; } int Pop_stu2(stu2 *L,int a) //操作数 出栈操作 { if(L->top==-1) { return 0; } else { a=L->data[L->top--]; } return a; } int GetTop_stu2(stu2 *L,int a) //操作数 取值操作 { if(L->top==-1) { return 0; } else { a=L->data[L->top]; } return a; } int Judge_optr(char a) //判断字符串ch是否属于运算符 { int x; //我们在这里定义这个函数的主要想法是 是实现比较运算符的优先级 switch(a) //和其他人写的 使用二位数组的原理是相同的 { case '(': case ')': x=0; break; case '+': case '-': x=1; break; case '*': case '/': x=2; break; } return x; } int Operate(int x,int y,char ch) //计算当前的值并将该值返回 { int a=0; switch(ch) { case '+': a=x+y; break; case '-': a=x-y; break; case '*': a=x*y; break; case '/': if(y==0) { printf("分母为零!!!"); return 0; } else { a=x/y; } break; default: printf("输入的数据错误n"); } return a; } void Jsbds(char str[]) { stu1 *optr=Init_stu1(); //初始化 符栈和数栈 stu2 *opnd=Init_stu2(); for(int i=0;str[i];i++) { char d[100]; //用来暂时存储数字型字符的 int j=0; int a; if(str[i]>'0' && str[i]<'9') //我们这里的if判断主要作用是判断输入的是否是1到9的字符 { do { d[j]=str[i]; i++; j++; }while(str[i]>='0' && str[i]<='9'); d[j]=' '; //这里面我们加 的主要原因是 因为我们的 是字符数组结束的标志 i--; //这里进行i--的原因是因为此时我们已经读到非数字位的字符 //若是不进行--for循环会自身进行--从而是我们跳过该字符入栈 //以上的do while 操作是使出现 十位和白位 a=atoi(d); //将字符型转化为数字型 Push(opnd,a); //进行入栈操作 } else { int b=0; char c=0; if(!Empty_stu1(optr) || Judge_optr(GetTop_stu1(optr,c)) > str; Jsbds(str); return 0; }
哈哈总的来说我觉的我的代码写的还行 就是有些小瑕疵 没有加什么限制条件。如果你在你的电脑上运行有误的话可能是编译器原因我用的是devc++6.5版本。
最后谢谢大家能够认真的看完。



