c语言实现中缀,后缀,前缀表达式转换并求值
C++中缀转后缀表达式并求值
C++中缀转后缀表达式并求值//中缀转后缀#include<iostream>#include<stack>using namespace std;int prio(char x){if(x=='*'||x=='/') return2;if(x=='+'||x=='-') return1;if(x=='(') return0;else return -1;}void in_to_post(char* inorder,char* &post){stack<char>S;int k=0;while(*inorder){//数字if(*inorder>='0'&&*inorder<='9'){post[k++] = *inorder;}//操作符else{if(S.empty()) {S.push(*inorder);}else if(*inorder=='('){S.push(*inorder);}else if(*inorder==')'){while(S.top()!='('){post[k++]=S.top();S.pop();}S.pop();}else{while(prio(*inorder)<=prio(S.top())){post[k++]=S.top();S.pop();if(S.empty()) break;}S.push(*inorder);}}inorder++;}if(!S.empty()){char c =S.top();post[k++] = c;S.pop();}}//后缀表达式求值int cal(int a,int b,char c){if(c=='+') return a+b;else if(c=='-') return a-b;else if(c=='*') return a*b;else if(c=='/') return a/b;else return0;}int postcal(char* post){stack <int > s;while(*post){if(*post >='0'&& *post<='9'){s.push(*post);}else{int a = s.top()-48;s.pop();int b = s.top()-48;s.pop();int c = cal(b,a,*post);s.push(c+48);}post++;}return s.top()-48;}int main(){cout<<"输⼊中缀表达式:"<<endl;char* inorder =new char;cin>>inorder;char* post= new char;cout<<"后缀表达式为:";in_to_post(inorder,post);cout<<post<<endl;int res = postcal(post);cout<<"后缀表达式计算结果:"<<res<<endl;}求解思想:中缀转后缀表达式: 从左到右扫描输⼊的中缀表达式,若是数字,则直接输出到结果,若是运算符则判断: 1. ‘(’ :直接⼊栈; 2. ‘)’:依次把栈中的运算符输出到结果,知道出现‘(’,将左括号从栈中删除; 3. 若是其他运算符,判断当前运算符与栈顶元素的优先级(*/为2,+-为1,(为0,其他为-1),若是当前运算符优先级较⾼,则直接⼊栈,否则,依次输⼊⽐当前运算符优先级⾼或相等的运算符,知道遇到不符合条件的元素或者遇到左括号为⽌,再将当前运算符⼊栈。
栈的应用1——超级计算器(中缀与后缀表达式)C语言
栈的应⽤1——超级计算器(中缀与后缀表达式)C语⾔这⾥要学的程序主要⽤来实现⼀个功能——输⼊表达式输出结果,也就是⼀个计算器。
效果如下:这个程序主要有两个步骤:1、把中缀表达式转换为后缀表达式;2、计算后缀表达式的结果。
⾸先先明⽩⼏个问题:1、为什么要转换为后缀表达式?因为后缀表达式容易实现计算机计算结果。
(可以百度⼀下后缀表达式,⼜称逆波兰式)2、怎么把中缀表达式转换为后缀表达式?3、怎么⽤后缀表达式输出结果?相信如果弄明⽩了上⾯⼏个问题,有C语⾔基础的同学就可以编出这个程序啦。
⽽后⾯两个问题都要⽤到⼀个数据结构——栈。
实际上数据结构只是⼀种思想,⼀种思维,是连接⼈脑与计算机的桥梁(纯属个⼈杜撰= =) 好,那么我们先学怎么把中缀表达式转换为后缀表达式。
为了简化问题,我们不妨设输⼊的数字都是⼀位整数,这样读⼊的时候只需要以字符的⽅式逐个读⼊即可,也就是说读⼊的必定是数字或者+-*/,读到回车视为结束;另外不妨直接将结果打印到屏幕上,也就是说结果不必存储(这样我们可以更多地关注算法本⾝,⽽⾮输⼊输出⽅式的细枝末节) 类似上⾯的图⽚,它的后缀表达式是 9 3 1 - 2 * + 5 2 / + 怎么得到的呢?下⾯开始讲这个转换的算法: 1、设置⼀个栈,栈底填⼀个"@"作为结束符(当然也可以⽤别的符号,⾄于为什么要⽤⼀会讲优先级的时候会说); 2、开始逐个字符读⼊; 3、如果读⼊的是数字,直接打印printf("%c ",c);(数字后⾯打印⼀个空格作为间隔符,要不然没法看了931-。
不解释) 4、如果读⼊的是"("直接进栈; 5、如果读⼊的是")",说明前⾯肯定读⼊过⼀个"("找到这个左括号,把两者之间的符号逐个弹栈(这⾥要说明的是,括号不必打印,因为后缀表达式没有括号); 6、如果不是上⾯的⼏种情况,那必定是+-*/中的⼀个啦,这样来说就容易多了。
C#算术表达式求值(后缀法),看这一篇就够了
C#算术表达式求值(后缀法),看这⼀篇就够了⼀、种类介绍算术表达式有三种:前缀表达式、中缀表达式和后缀表达式。
⼀般⽤的是中缀,⽐如1+1,前后缀就是把操作符移到前⾯和后⾯,下⾯简单介绍⼀下这三种表达式。
1、前缀表⽰法前缀表⽰法⼜叫波兰表⽰法,他的操作符置于操作数的前⾯(例:+ 1 2),是波兰数学家扬·武卡谢维奇1920年代引⼊的,⽤于简化命题逻辑。
因为我们⼀般认为操作符是在操作数中间的,所以在⽇常⽣活中⽤的不多,但在计算机科学领域占有⼀席之地。
⼀般的表⽰法对计算机来说处理很⿇烦,每个符号都要考虑优先级,还有括号这种会打乱优先级的存在,将使计算机花费⼤量的资源进⾏解析。
⽽前缀表⽰法没有优先级的概念,他是按顺序处理的。
举个例⼦:9-2*3这个式⼦,计算机需要先分析优先级,先乘后减,找到2*3,再进⾏减操作;化成前缀表⽰法就是:- 9 * 2 3,计算机可以依次读取,操作符作⽤于后⼀个操作数,遇到减就是让9减去后⾯的数,⽽跟着9的是乘,也就是说让9减去乘的结果,这对计算机来说很简单,按顺序来就⾏了。
2、中缀表⽰法这也就是我们⼀般的表⽰法,他的操作符置于操作数的中间(例:1 + 2),前⾯也说过这种⽅法不容易被计算机解析,但他符合⼈们的普遍⽤法,许多编程语⾔也就⽤这种⽅法了。
在中缀表⽰法中括号是必须有的,要不然运算顺序会乱掉。
3、后缀表⽰法后缀表⽰法⼜叫逆波兰表⽰法,他的操作符置于操作数的后⾯(例:1 2 +),他和前缀表⽰法都对计算机⽐较友好,但他很容易⽤堆栈解析,所以在计算机中⽤的很多。
他的解释过程⼀般是:操作数⼊栈;遇到操作符时,操作数出栈,求值,将结果⼊栈;当⼀遍后,栈顶就是表达式的值。
因此逆波兰表达式的求值使⽤堆栈结构很容易实现,且能很快求值。
注意:逆波兰记法并不是简单的波兰表达式的反转。
因为对于不满⾜交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法/ 6 3的逆波兰记法是6 3 /⽽不是3 6 /;数字的数位写法也是常规顺序。
c语言实现中缀表达式的计算
c语言实现中缀表达式的计算C语言实现中缀表达式的计算一、前言在计算机科学领域,中缀表达式是最容易理解的数学表达式,也是人们最常用的表达方式。
但对于计算机而言,中缀表达式并不方便计算。
因此,在进行表达式计算时,需要将中缀表达式转化为其它形式,例如前缀表达式和后缀表达式。
在本篇文章里,我们将介绍如何使用C语言实现中缀表达式的计算。
二、中缀表达式的转换在C语言中,实现中缀表达式的计算,通常需要先将中缀表达式转换为后缀表达式。
中缀表达式的转换过程主要分为以下三个步骤:1. 初始化一个栈,存储操作符。
2. 遍历中缀表达式,根据操作符的运算优先级将其从中缀表达式转化为后缀表达式。
3. 根据后缀表达式,使用栈实现表达式的计算。
其中,第二步是最关键的一个步骤。
我们可以通过以下方法进行转换:1. 将操作数直接输出。
2. 如果遇到运算符,先将栈中所有优先级大于等于该运算符的操作符弹出,再将该运算符入栈。
3. 如果遇到左括号,直接入栈。
4. 如果遇到右括号,将栈中的元素一直弹出到遇到左括号为止。
例如,对于中缀表达式2 + 3 * 4 - 5,转换为后缀表达式的过程如下所示:中缀表达式:2 + 3 * 4 - 5转换为后缀表达式:2 3 4 * + 5 -三、代码实现现在,我们已经掌握了中缀表达式的转换方法,接下来,我们就可以实现C语言代码了。
具体实现如下:#include <stdio.h>#include <stdlib.h>#include <string.h>// 定义运算符栈char op_stack[100];// 定义数字栈int num_stack[100];// 定义存储后缀表达式的数组char postfix[100];// 定义存储后缀表达式的栈顶指针int postIndex = 0;// 获取优先级int getPriority(char op){switch(op){case '+':case '-':return 1;case '*':case '/':return 2;case '(':case ')':return 0;}return -1;}// 中缀表达式转换为后缀表达式void infixToPostfix(char* infix){// 定义中缀表达式的指针char* ptr = infix;// 定义操作符栈顶指针int opTop = 0;while(*ptr != '\0'){if(*ptr >= '0' && *ptr <= '9') // 如果是数字,直接存入后缀表达式{postfix[postIndex++] = *ptr;}else if(*ptr == '(') // 如果是左括号,先入栈{op_stack[opTop++] = *ptr;}else if(*ptr == ')') // 如果是右括号,将栈中元素全部弹出{while(op_stack[opTop-1] != '('){postfix[postIndex++] = op_stack[--opTop];}opTop--;}else // 如果是运算符{while(opTop > 0 && getPriority(op_stack[opTop-1]) >= getPriority(*ptr)) // 将栈中优先级大于等于当前运算符的元素全部弹出{postfix[postIndex++] = op_stack[--opTop];}op_stack[opTop++] = *ptr; // 将当前运算符入栈}ptr++;}while(opTop > 0) // 将栈中剩余运算符全部弹出{postfix[postIndex++] = op_stack[--opTop];}}// 计算后缀表达式int calculate(char* postfix){// 定义后缀表达式的指针char* ptr = postfix;// 定义数字栈顶指针int numTop = 0;while(*ptr != '\0'){if(*ptr >= '0' && *ptr <= '9') // 如果是数字,直接入栈{num_stack[numTop++] = *ptr - '0';}else // 如果是运算符{int num2 = num_stack[--numTop];int num1 = num_stack[--numTop];switch(*ptr){case '+':num_stack[numTop++] = num1 + num2;break;case '-':num_stack[numTop++] = num1 - num2;break;case '*':num_stack[numTop++] = num1 * num2;break;case '/':num_stack[numTop++] = num1 / num2;break;}}ptr++;}return num_stack[0];}// 测试函数void test(char* infix){printf("中缀表达式:%s\n", infix);infixToPostfix(infix);printf("后缀表达式:%s\n", postfix);int result = calculate(postfix);printf("计算结果:%d\n", result);printf("--------------------------\n");}// 主函数int main(){test("2 + 3 * 4 - 5");test("3 + 4 * 2 / (1 - 5) ^ 2");return 0;}四、总结通过以上代码实现,我们可以看到中缀表达式的计算过程,其实就是将中缀表达式转化为后缀表达式的过程,并使用栈进行计算。
前缀、中缀、后缀表达式的相互转换方法
前缀、中缀、后缀表达式的相互转换⽅法前缀式、中缀式、后缀式相互转换⼀. 中缀式转化成前缀式和后缀式:⼀个中缀式到其他式⼦的转换⽅法这⾥我给出⼀个中缀表达式a +b *c - (d +e )第⼀步:按照运算符的优先级对所有的运算单位加括号式⼦变成:( ( a + ( b * c ) ) - ( d + e ) )第⼆步:转换前缀与后缀表达式中缀转前缀:把运算符号移动到对应的括号前⾯则变成:- ( + ( a * ( b c ) ) + ( d e ) )把括号去掉:- + a * b c + d e 前缀式⼦出现中缀转后缀:把运算符号移动到对应的括号后⾯则变成:( ( a ( b c ) * ) + ( d e ) + ) -把括号去掉:a b c * + d e + - 后缀式⼦出现⼆. 前缀式转化成中缀式:+ a * b c + d e从后往前遇到运算符,将其与后⾯两个运算数结合,加上括号,当成新的运算数(例如:* b c 加上括号,变成 ( * b c )⼀个整体,作为运算数)变成:( - ( + a ( * b c ) ) ( + d e ) )将运算符加在括号内运算数中间。
变成:( ( a + ( b * c ) ) - ( d + e ) )去掉部分括号:a + b * c - ( d + e )(最后去掉的是不影响运算式含义的多余括号)三. 后缀式转化成中缀式:a b c * + d e + -从前往后遇到运算符,将其与前⾯两个运算数结合,加上括号,当成新的运算数变成:( ( a ( b c * ) + ) ( d e + ) - )将运算符加在括号内运算数中间。
变成:( ( a + ( b * c ) ) - ( d + e ) )去掉部分括号:a + b * c - ( d + e )(最后去掉的是不影响运算式含义的多余括号)。
中缀表达式转后缀表达式并计算结果(c语言版)
中缀表达式转后缀表达式中缀表达式转后缀表达式的规则。
1.遇到操作数:直接输入到后缀表达式栈2.遇到运算符,直接入操作符栈3.遇到左括号:直接将其入栈4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈6.最终将操作符栈中的元素依次出栈,输出到后缀表达式栈。
以下是自己写的代码。
亲测没有问题。
(模拟一个计算器,可以带括号,中间可以空格,只支持整数输入,但是输出结果精确到小数后6位)#include "stdio.h"#define MAX_LEN 100typedef struct cal{unsigned char isOper;//是否是操作数1,操作符0.操作数double Num; //值。
或者是操作符的ASCII值}STRUCT_CAL;#define IS_NUM 0x00#define IS_OPER 0x01STRUCT_CAL stackCal[MAX_LEN];STRUCT_CAL stackCalBack[MAX_LEN];unsigned char topCal;char stackOper[MAX_LEN];unsigned char topOper;/****************************************************************** 堆栈初始化*****************************************************************/void stackInit(void){int i;for(i=0;i<MAX_LEN;i++){stackCal[i].isOper = 0;stackCal[i].Num = 0;stackOper[i] = 0;}topCal = topOper = 0;}/***************************************************************** * 返回堆栈的栈顶,返回后栈顶减一*****************************************************************/ STRUCT_CAL * stackCalPop(void){if(topCal == 0)return (STRUCT_CAL *)0;return stackCal+(--topCal);}/***************************************************************** * 计算表达式入栈*****************************************************************/void stackCalPush(double num, unsigned char isOper){if(topCal>=MAX_LEN)return;stackCal[topCal].Num = num;stackCal[topCal].isOper= isOper;topCal++;}/***************************************************************** * 操作符出栈*****************************************************************/char stackOperPop(void){if(topOper == 0)return 0;return stackOper[--topOper];}/****************************************************************** 操作符入栈*****************************************************************/void stackOperPush(char oper){if(topOper >=MAX_LEN)return;stackOper[topOper++] = oper;}/****************************************************************** 比较两个sour sour1 的优先级* 1 sour >= sour1 直接入操作符栈* 0 sour < sour1 直接入计算表达式栈*****************************************************************/ unsigned char comparPrior(char sour, char sour1){if(sour =='\0' ||sour1 == '\0') return 1;switch(sour){case '+':case '-':if(sour1 == '*' ||sour1 == '/'||sour1 == '+' ||sour1 == '-' ){return 0;}else{return 1;}break;case '*':case '/':if(sour1 == '*' ||sour1 == '/'||sour1 == '+' ||sour1 == '-'||sour1 == '('){return 1;}else{return 0;}break;default:return 1;break;}}/****************************************************************** 将输入的字符串转换为栈*****************************************************************/void StrToCal(char *pStr){int tmpNum = 0;char tmpOper;char islastNum = 0;//判断上一个字符是什么。
c语言基于二叉树的表达式求值算法
c语言基于二叉树的表达式求值算法C语言中,基于二叉树的表达式求值算法主要包括两部分:中缀表达式转换为后缀表达式和后缀表达式求值。
1.中缀表达式转换为后缀表达式中缀表达式是我们常见的数学表达方式,例如3 + 4 * 2 - 5。
为了方便计算机求值,我们需要将中缀表达式转换为后缀表达式,也叫做逆波兰表达式。
转换的过程使用栈数据结构来实现。
具体算法如下:1.定义一个栈和一个结果字符串,栈用于存储操作符,结果字符串用于保存后缀表达式。
2.从左到右遍历中缀表达式的每一个字符。
3.如果当前字符是数字,直接将其加入结果字符串。
4.如果当前字符是左括号"(",将其入栈。
5.如果当前字符是右括号")",则依次将栈顶的操作符弹出并加入结果字符串,直到遇到左括号为止,同时将左括号从栈中弹出。
6.如果当前字符是操作符,需要将栈中优先级比当前操作符高或者相等的操作符弹出并加入结果字符串,然后将当前操作符入栈。
7.遍历完所有字符后,将栈中剩余的操作符依次弹出并加入结果字符串。
8.最终结果字符串就是后缀表达式。
例如,对于中缀表达式3 + 4 * 2 - 5,转换为后缀表达式为3 4 2 * + 5 -2.后缀表达式求值后缀表达式求值算法使用栈数据结构来实现。
具体算法如下:1.定义一个栈,用于存储操作数。
2.从左到右遍历后缀表达式的每一个字符。
3.如果当前字符是数字,则将其转换为对应的整数并入栈。
4.如果当前字符是操作符,则从栈中弹出两个操作数,先弹出的作为右操作数,后弹出的作为左操作数,根据操作符进行运算,得到结果后入栈。
5.遍历完所有字符后,栈顶的数字即为最终的结果。
例如,对于后缀表达式3 4 2 * + 5 -,求值的过程如下:1.入栈3。
2.入栈4。
3.入栈2。
4.弹出2和4,计算4 * 2 = 8,将8入栈。
5.弹出8和3,计算3 + 8 = 11,将11入栈。
6.入栈5。
7.弹出5和11,计算11 - 5 = 6,得到最终结果。
前缀、中缀、后缀表达式的转换(栈)
前缀、中缀、后缀表达式的转换(栈)
前缀表达式:op a b
中缀表达式:a op b
后缀表达式 a b op
1、对于计算单独的后缀表达式较为简单,从左到右,遇到数字将其压⼊栈内,遇到操作符从栈中取出两个数进⾏相应操作,结果再次压⼊栈内。
2、对于前缀表达式的计算和后缀相似,从右到左的顺序,剩下和后缀⼀致
3、对于中缀表达式,我们可以选择将其转换成前缀或者后缀表达式。
中缀转后缀:(从左到右)
1、遇到⼀个数字就输出(毕竟不管中缀和后缀,都只是操作符位置的改变,和数字⽆关)
2、遇到‘( ’直接压⼊栈
3、遇到’ )‘将栈中操作符输出,直到输出’( ‘ (括号内相当于另⼀个后缀表达式,当遇到’)‘时,就将括号内的符号都输出)
4、遇到操作符,将栈中优先级不低于的符号输出,然后将操作符压⼊栈(乘除 > 加减 > 左括号)(因为优先级⾼的需要先运算,优先级相同的因为先出现所以先运算)
5、最后输出栈中剩下的所有操作符
中缀转前缀:(从右到左)
1、遇到⼀个数字就输出到临时栈(毕竟不管中缀和前缀,都只是操作符位置的改变)
2、遇到‘ ) ’直接压⼊符号栈
3、遇到’ (‘将符号栈中操作符输出,直到输出’) ‘
4、遇到操作符,将栈中优先级⼤于的符号输出,然后将操作符压⼊符号栈(乘除 > 加减 > 右括号)
(优先级相同之所以不出栈,因为输出的前缀时倒序的,优先级相同应该在更后⾯输出,这样倒过来才是最前⾯)
5、最后输出符号栈中剩下的所有操作符⾄临时栈
6、然后输出临时栈中的结果(输出出来的才是前缀表达式)。
用栈解决表达式求值问题的c语言代码
栈是一种常见的数据结构,用于解决许多算法和数据处理问题。
在编程中,栈通常用于处理表达式求值问题。
本篇文章将介绍如何使用栈解决表达式求值问题,并给出对应的C语言代码。
1. 表达式求值问题介绍表达式求值是指计算一个数学表达式的值,通常涉及到四则运算、括号和优先级等概念。
给定一个表达式“3 + 4 * 2”,我们需要得到其计算结果为11。
在编程中,需要将该表达式转换为计算机可识别的形式,并使用算法进行求值。
2. 中缀表达式、前缀表达式和后缀表达式在计算机中常见的表达式有三种形式:中缀表达式、前缀表达式和后缀表达式。
其中,中缀表达式是通常人们在日常生活中使用的表达式形式,如“3 + 4 * 2”。
前缀表达式是运算符位于操作数之前的形式,例如“+ 3 * 4 2”。
后缀表达式则是运算符位于操作数之后的形式,例如“3 4 2 * +”。
3. 使用栈解决表达式求值问题在解决表达式求值问题时,我们可以利用栈的特性来简化计算过程。
具体步骤如下:3.1 将中缀表达式转换为后缀表达式我们需要将中缀表达式转换为后缀表达式,这样可以简化表达式的计算顺序。
具体转换规则如下:- 从左至右扫描中缀表达式的每个数字或符号。
- 如果是操作数,则直接输出。
- 如果是运算符,则弹出栈中所有优先级大于或等于该运算符的运算符,并将其压入栈中,然后压入该运算符。
- 如果是括号,则根据括号的不同情况进行处理。
通过以上规则,我们可以将中缀表达式转换为后缀表达式。
3.2 计算后缀表达式的值得到后缀表达式后,我们可以利用栈来计算其值。
具体步骤如下:- 从左至右扫描后缀表达式的每个数字或符号。
- 如果是操作数,则压入栈中。
- 如果是运算符,则弹出栈中的两个操作数进行相应的运算,并将结果压入栈中。
- 继续扫描直到表达式结束,栈中的值即为所求结果。
通过以上步骤,我们可以使用栈来解决表达式求值问题。
4. C语言代码实现以下是使用C语言实现栈来解决表达式求值问题的代码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct {int top;int capacity;int* array;} Stack;Stack* createStack(int capacity) {Stack* stack = (Stack*)malloc(sizeof(Stack));stack->capacity = capacity;stack->top = -1;stack->array = (int*)malloc(stack->capacity * sizeof(int)); return stack;}int isFull(Stack* stack) {return stack->top == stack->capacity - 1; }int isEmpty(Stack* stack) {return stack->top == -1;}void push(Stack* stack, int item) {if (isFull(stack)) return;stack->array[++stack->top] = item;}int pop(Stack* stack) {if (isEmpty(stack)) return -1;return stack->array[stack->top--];}int evaluatePostfix(char* exp) {Stack* stack = createStack(strlen(exp)); for (int i = 0; exp[i]; i++) {if (isdigit(exp[i])) {push(stack, exp[i] - '0');} else {int val1 = pop(stack);int val2 = pop(stack);switch (exp[i]) {case '+':push(stack, val2 + val1); break;case '-':push(stack, val2 - val1); break;case '*':push(stack, val2 * val1); break;case '/':push(stack, val2 / val1); break;}}}return pop(stack);}int m本人n() {char exp[] = "34*2+";printf("The value of s is d\n", exp, evaluatePostfix(exp));return 0;}```以上代码实现了栈的基本功能,并利用栈来计算后缀表达式的值。
C语言实现中缀、后缀、前缀表达式 相互转化并求值
C语言实现中缀、后缀、前缀表达式相互转化并求值1.问题描述(1)表达式求值问题表达式是数据运算的基本形式。
人们的书写习惯是中缀式,如:11+22*(7-4)/3。
中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进行计算。
表达式还有后缀式(如:22 7 4 - * 3 / 11 +)和前缀式(如:+ 11 / * 22 –7 4 3)。
后缀表达式和前缀表达式中没有括号,给计算带来方便。
如后缀式计算时按运算符出现的先后进行计算。
本设计的主要任务是进行表达式形式的转换及不同形式的表达式计算。
2.数据结构设计(1)表达式求值问题由于表达式中有字符与数字两种类型,故定义结点一个标志域data,标志结点存储的为字符data=2还是数字data=1,再寻找结点中对应的存储位置,读取数字域data1,字符域data2。
而在前缀表达式时,存在表达式逆序,因表达式类型不统一,用栈逆序极不方便,选择构建双向链表,存储表达式。
typedef struct Node //定义存储中缀表达式的结点类型{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2 //定义存储前缀表达式的结点类型{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;3.运行、测试与分析(1)表达式求值问题(1)按提示输入中缀表达式,如图1.1所示。
如输入中缀表达式不正确,提示输入有误,如图1.2,1.3所示。
图1.1图1.2图1.3(2)选择表达式转换并求值方式。
按“1”选择中缀表达式求值,如图1.4所示。
图1.4(3)按“2”选择中缀表达式转变为后缀表达式并求值,如图1.5所示。
图1.5(4)按“3”选择中缀表达式转变为前缀表达式并求值,如图1.6所示。
c语言表达式求值中缀表达式转后缀表达式求值
c语⾔表达式求值中缀表达式转后缀表达式求值中转后具体转换⽅式:1.从左到右遍历需要计算的字符串2.若是运算数,直接压⼊后缀表达式栈3.若是左括号,直接压⼊运算符栈,(括号是最⾼优先级,⽆需⽐较)(⼊栈后优先级降到最低,确保其他符号正常⼊栈)4.若是右括号,(意味着括号已结束)不断弹出运算符栈顶运算符并输出到后缀表达式栈直到遇到左括号(弹出但不输出)5.运算符,将该运算符与运算符栈顶运算符进⾏⽐较,如果优先级⾼于栈顶运算符则压⼊运算符栈(该部分运算还不能进⾏),如果优先级低于等于栈顶运算符则将栈顶运算符弹出到后缀表达式栈然后⽐较新的栈顶运算符.(低于弹出意味着前⾯部分可以运算,先输出到后缀表达式栈⼀定是⾼优先级运算符,等于弹出是因为同等优先级,从左到右运算)直到优先级⼤于栈顶运算符或者栈空,再将该运算符⼊运算符栈6.如果字符串处理完毕,则按顺序从运算符栈弹出所有运算符到后缀表达式栈使⽤后缀表达式计算的⽅法:1、按顺序取后缀表达式的每个值2、若是数字则⼊栈3、若是操作符则从栈取出两个数字进⾏运算运算之后再将结果⼊栈4、循环上述过程知道后缀表达式结束栈顶元素(栈中只有⼀个元素)即为结果1 #include <windows.h>2 #include <stdio.h>3 #include <string.h>4 #include <malloc.h>5#define NUM 06#define OPERATION 17 typedef struct {//栈中的结点8int val;9int type;10 } Node;11 typedef struct {//栈12const char* name;//栈名13 Node* sta;//结点14int size;//最多存储多少个元素15int cnt;//当前存储了多少个元素16 } MyStack;17void trace(MyStack* s)//栈的遍历18 {19int i;20 printf("%s栈中的元素为:", s->name);21for (i = 0; i < s->cnt; i++) {22if (s->sta[i].type == NUM) {//若是数字23 printf("%d ", s->sta[i].val);24 }25else {//若是字符26 printf("%c ", (char)s->sta[i].val);27 }28 }29 printf("\n");30 }31void sFree(MyStack* s)//释放栈32 {33if (s->sta != NULL) {34 free(s->sta);35 s->sta = NULL;36 }37return;38 }39int sInit(MyStack* s, const char* name, int size)//初始化栈40 {41 s->name = name;42 s->size = size;43 s->sta = (Node*)calloc(s->size, sizeof(Node));//calloc申请后其中存的都是044if (s->sta == NULL) {45return -1;//分配失败46 }47 s->cnt = 0;//当前栈中元素有0个48return0;//分配成功49 }50void sPush(MyStack* s, Node item)//⼊栈⼀个元素51 {52if (s->cnt == s->size) {53 printf("栈空间不⾜\n");54return;55 }56 s->sta[s->cnt] = item;57 s->cnt++;58return;59 }60bool sIsEmpty(MyStack* s)//判断栈是否为空61 {62return s->cnt == 0;63 }64void sPop(MyStack* s, Node* item)//删除栈顶元素并返回值到item65 {66if (sIsEmpty(s)) {67return;68 }69 *item = s->sta[s->cnt - 1];70 s->cnt--;71return;72 }73void sTop(MyStack* s, Node* item)//获得栈顶元素到item 不删除栈顶袁术74 {75if (sIsEmpty(s)) {76return;77 }78 *item = s->sta[s->cnt - 1];79return;80 }81bool myIsNum(char ch)//判断是否是数字82 {83return ch >= '0' && ch <= '9';84 }85bool myIsOper(char ch)//判断是否是运算符86 {87return ch == '+' || ch == '-' || ch == '*' || ch == '/'||ch=='('||ch==')';88 }89//处理数值90void procNum(MyStack* postfix_expression, char* s, int len, int* pi)91 {92int i = *pi;//令i等于当前在处理的元素的坐标93int num=0;//当前数字的值具体是多少94 Node item_num;95while (myIsNum(s[i]))96 {97 num = num * 10 + s[i]-'0';98 i++;99 }100//新建结点101 item_num.type = NUM;102 item_num.val = num;103//数字直接⼊后缀表达式的栈104 sPush(postfix_expression, item_num);105 *pi = i-1;//改变calculate_postfix_expression 中i的值106return;107 }108//处理运算符109void procOper(MyStack* postfix_expression, MyStack* s_oper, char* s, int len, int* pi) 110 {111int i = *pi;112 Node item;113 Node top_item;114 Node pop_item;115if (s[i] == '(')//如果是( 直接存⼊运算符栈116 {117 item.type = OPERATION;118 item.val = s[i];119 sPush(s_oper, item);120 }121else if (s[i] == ')')//若是) 则弹出到(为⽌122 {123int flag = 0;//是否找到了 (124while (!sIsEmpty(s_oper)) {125 sPop(s_oper, &pop_item);126if (pop_item.val == '(') {//若找到了左括号退出127 flag = 1;128break;129 }130 sPush(postfix_expression, pop_item);//若未找到左括号则⼀直从运算符栈中pop131 }132if (!flag)133 {134 printf("括号不匹配!");135 exit(0);136 }137 }138//如果是乘除139else if (s[i] == '*' || s[i] == '/')140 {141 item.type = OPERATION;142 item.val = s[i];143while (!sIsEmpty(s_oper)) {144 sTop(s_oper, &top_item);145//如果当前运算符栈的栈顶是+ - (146//则* /级别较⾼则跳出循环147if (top_item.val == '+' || top_item.val == '-' || top_item.val == '(') {148break;149 }150//若当前运算符栈顶不是+ - ( 则是* /151//则需先把* / pop完152 sPop(s_oper, &pop_item);153 sPush(postfix_expression, pop_item);154 }155//才能将当* /⼊栈156 sPush(s_oper, item);157 }158//如果是 + -159else if (s[i] == '+' || s[i] == '-')160 {161 item.type = OPERATION;162 item.val = s[i];163while (!sIsEmpty(s_oper)) {164 sTop(s_oper, &top_item);165//如果当前运算符栈的栈顶是 (166//则当前运算符级别较⾼则跳出循环167if (top_item.val == '(') {168break;169 }170//若当前运算符栈顶不是 ( 则是+ - * /171//则需先把+ - * /pop完172 sPop(s_oper, &pop_item);173 sPush(postfix_expression, pop_item);174 }175//才能将当+ - ⼊栈176 sPush(s_oper, item);177 }178else179 {180 printf("输⼊了⾮空格⾮数字⾮运算符的元素 %c\n", s[i]);181 exit(0);182 }183return;184 }185//计算后缀表达式存储在s_trans中186void calculate_postfix_expression(MyStack* postfix_expression, MyStack* s_oper, char* s, int len) 187 {188int i;189int ret;190int num;191 Node item;192for (i = 0; i < len; i++) {193if (s[i] == '') {//当前输⼊为空格时跳过194continue;195 }196if (myIsNum(s[i])) {//当前是数字时197 procNum(postfix_expression, s, len, &i);198continue;199 }200if (myIsOper(s[i])) {//当前是运算符时进⼊运算的处理程序201 procOper(postfix_expression, s_oper, s, len, &i);202continue;203 }204 printf("输⼊了⾮空格⾮数字⾮运算符的元素 %c\n", s[i]);205 exit(0);206 }207//若运算栈不为空依次pop出运算栈中的元素再push到后缀表达式栈208while (!sIsEmpty(s_oper)) {209 sPop(s_oper, &item);210 sPush(postfix_expression, item);211 }212return;213 }214int cal(MyStack* postfix_expression, MyStack* s_num)//进⾏计算215 {216int i;217 Node n1, n2;218 Node item;219//顺序取出栈中的每个元素220for (i = 0; i < postfix_expression->cnt; i++) {221//item为后缀表达式中顺序取的第i个元素222 item = postfix_expression->sta[i];223//若⼀直是数字则⼀直放进数字栈224if (item.type == NUM) {225 sPush(s_num, item);226continue;//开始下⼀次循环227 }228//执⾏到这⾥证明不是数字是运算符了229 sPop(s_num, &n2);//从栈中拿出两个元素到n2 n1中230 sPop(s_num, &n1);231if (item.val == '+') {232 n1.val += n2.val;233 }234else if (item.val == '-') {235 n1.val -= n2.val;236 }237else if (item.val == '*') {238 n1.val *= n2.val;239 }240else {241 n1.val /= n2.val;242 }243 sPush(s_num, n1);//再将此次运算结果⼊数字栈244 }245return s_num->sta[0].val;//最后数字栈中的第⼀个元素就是计算结果246 }247int calculate(char* s) {//进⾏计算248int ret;249int len;250if (s == NULL||(len=strlen(s))==0) {251return0;252 }253 MyStack s_num;//数字栈254 MyStack s_oper;//运算符栈255 MyStack postfix_expression;//后缀表达式栈256if (sInit(&s_num, "数字", len)==-1||257 sInit(&s_oper, "运算符", len)==-1||258 sInit(&postfix_expression, "后缀表达式", len)==-1259 ) //若初始化三个栈失败的话则释放内存 return 0260 {261 sFree(&s_num);262 sFree(&postfix_expression);263 sFree(&s_oper);264return0;265 }266//计算后缀表达式267 calculate_postfix_expression(&postfix_expression, &s_oper, s, len); 268//显⽰后缀表达式269 trace(&postfix_expression);270//使⽤后缀表达是进⾏计算271 ret = cal(&postfix_expression, &s_num);272//释放栈的空间273 sFree(&postfix_expression);274 sFree(&s_oper);275 sFree(&s_num);276//返回结果277return ret;278 }279int main()280 {281char str[10000];282 scanf("%[^\n]", str);//可以输⼊空格回车停⽌输⼊283 printf("计算结果为%d\n", calculate(str));284 }285//例⼦ (((50+20)+(2*3))/14)。
c 实现中缀表达式转后缀表达式比计算值
c 实现中缀表达式转后缀表达式比计算值C语言是一种广泛应用的编程语言,它具有高效、可移植、灵活等特点,在计算机科学领域有着广泛的应用。
中缀表达式是我们常见的数学表达方式,而将中缀表达式转换为后缀表达式是一项常见的任务。
本文将介绍如何使用C语言实现中缀表达式转后缀表达式,并计算其值。
我们需要了解中缀表达式和后缀表达式的概念。
中缀表达式是我们常见的数学表达方式,其中操作符位于操作数之间,如"3 + 4"。
而后缀表达式(也称为逆波兰表达式)是一种更加简洁的数学表达方式,其中操作符位于操作数之后,如"3 4 +"。
后缀表达式的计算更加简单直观,因此在计算机中更为常见。
接下来,我们需要实现一个函数来将中缀表达式转换为后缀表达式。
我们可以使用栈这一数据结构来辅助实现。
具体的步骤如下:1. 创建一个栈,用于存储操作符。
2. 遍历中缀表达式的每个字符。
3. 如果当前字符是操作数,直接输出。
4. 如果当前字符是操作符,并且栈为空,将操作符入栈。
5. 如果当前字符是操作符,并且栈不为空,比较当前操作符与栈顶操作符的优先级。
- 如果当前操作符的优先级大于栈顶操作符的优先级,将当前操作符入栈。
- 如果当前操作符的优先级小于等于栈顶操作符的优先级,将栈顶操作符出栈并输出,直到栈为空或者栈顶操作符的优先级小于当前操作符。
- 将当前操作符入栈。
6. 如果当前字符是左括号"(",将其入栈。
7. 如果当前字符是右括号")",将栈顶操作符出栈并输出,直到栈顶操作符为左括号"("。
8. 遍历结束后,将栈中剩余的操作符依次出栈并输出。
通过上述步骤,我们可以将中缀表达式转换为后缀表达式。
接下来,我们需要计算后缀表达式的值。
为了计算后缀表达式的值,我们可以使用另一个栈来辅助实现。
具体的步骤如下:1. 创建一个栈,用于存储操作数。
2. 遍历后缀表达式的每个字符。
中缀、前缀、后缀表达式的运算
中缀、前缀、后缀表达式的运算 中缀表达式,就是在表达式中,操作符在操作数的中间,⽐如 (1+2)*3,+和*在1, 2, 3的中间。
前缀表达式,就是操作符在操作数的前⾯,⽐如 +12,+在1, 2的前⾯。
后缀表达式,就是操作符在操作数的后⾯,⽐如 12+,+在1, 2的后⾯。
为什么会有这么多表达式呢?它们⽬的不同。
中缀表达式,便于我们书写,也符合我们的阅读习惯,在计算机程序中,都是写中缀表达式,但它却不利于计算机进⾏算术计算,因为涉及到优先级和括号。
前缀表达式和后缀表达式中没有括号,并且运算符的优先级也通过它们在表达式中的顺序体现出来了,有利于计算机进⾏算术运算。
前缀表达式也叫波兰表达式,因为它是由⼀个波兰⼈发明的,相应的,后缀表达式也称为逆波兰表达式。
举个例⼦来说明⼀下三者的运算过程,假设计算(3+4)*5-6 使⽤中缀表达式进⾏计算 1,创建两个栈,⼀个是数字栈,⽤来存放操作数,⼀个是字符栈,⽤来存放操作符。
2,算术表达式是⼀个字符串,从左到右循环遍历表达式,依次取出每⼀个字符。
当取出的字符是操作数时,⼊数字栈。
当取出的字符是操作符时,这时还要看操作符的优先级和字符栈是否为空 如果字符栈为空,直接把取出的字符放⼊到字符栈中。
如果字符栈不为空,则要⽐较字符的优先级 如果取出的字符的优先级⼤于等于字符栈中栈顶的字符的优先级,直接把取出的字符放⼊到字符栈中。
如果取出的字符的优先级⽐字符栈中栈顶的字符的优先级低,则要循环进⾏如下操作,直到取出的字符的优先级⼤于等于字符栈中栈顶字符的优先级或者栈为空,此时,把取出的字符放⼊到字 符栈中。
如下操作就是: 1,从字符栈中弹出操作符 2,从数字栈中弹出两个操作数。
3,操作数结合操作符进⾏计算,要注意操作数顺序,后⾯pop出的数在求值的表达式中是前⾯的操作数,尤其是在做减法的时候 4,计算出的值放⼊到数字栈。
为什么要⽐较操作符的优先级呢?因为要确定操作数属于哪个操作符,相邻两个操作符之间的数字是共享的。
(完整版)数学表达式计算(c语言实现)
一、设计思想计算算术表达式可以用两种方法实现:1.中缀转后缀算法此算法分两步实现:先将算术表达式转换为后缀表达式,然后对后缀表达式进行计算。
具体实现方法如下:(1)中缀转后缀需要建一个操作符栈op和一个字符数组exp,op栈存放操作符,字符数组用来存放转换以后的后缀表达式。
首先,得到用户输入的中缀表达式,将其存入str数组中。
对str数组逐个扫描,如果是数字或小数点,则直接存入exp数组中,当扫描完数值后,在后面加一个#作为分隔符。
如果是操作符,并且栈为空直接入栈,如果栈不为空,与栈顶操作符比较优先等级,若比栈顶优先级高,入栈;如果比栈顶优先级低或相等,出栈将其操作符存到exp数组中,直到栈顶元素优先等级低于扫描的操作符,则此操作符入栈;如果是左括号,直接入栈,如果是右括号,出栈存入exp数组,直到遇到左括号,左括号丢掉。
然后继续扫描下一个字符,直到遇到str中的结束符号\0,扫描结束。
结束后看op栈是否为空,若不为空,继续出栈存入exp数组中,直到栈为空。
到此在exp数组最后加结束字符\0。
我们就得到了后缀表达式。
(2)后缀表达式计算此时需要一个数值栈od来存放数值。
对exp数组进行逐个扫描,当遇到数字或小数点时,截取数值子串将其转换成double类型的小数,存入od栈中。
当遇到操作符,从栈中取出两个数,进行计算后再放入栈中。
继续扫描,知道扫描结束,此时值栈中的数值就是计算的结果,取出返回计算结果。
2.两个栈实现算法此算法需要两个栈,一个值栈od,一个操作符栈op。
将用户输入的数学表达式存入str数组中,对其数组进行逐个扫描。
当遇到数字或小数点,截取数值子串,将其转换成double类型的数值存入od栈中;当遇到左括号,直接入op栈;遇到右括号,op栈出栈,再从值栈od中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到操作符栈栈顶为左括号,将左括号丢掉。
如果遇到操作符,若op栈为空,直接入栈;若栈不为空,与栈顶元素比较优先等级,若比栈顶操作符优先等级高,直接入op栈,如果低于或等于栈顶优先等级,op栈出栈,再从值栈中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到栈顶优先等级低于扫描的操作符等级,将此操作符入op栈。
c语言中缀、后缀算术表达式求值用栈实现
c语言中缀、后缀算术表达式求值用栈实现下面是用栈实现中缀表达式求值的示例代码:#include <stdio.h>#include <stdlib.h>#include <ctype.h>#define MAX_STACK_SIZE 100typedef struct {int top;int data[MAX_STACK_SIZE];} Stack;void init(Stack *s) {s->top = -1;}int is_empty(Stack *s) {return s->top == -1;}int is_full(Stack *s) {return s->top == MAX_STACK_SIZE - 1;}void push(Stack *s, int x) {if (is_full(s)) {printf("Error: stack overflow\n");exit(EXIT_FAILURE);}s->data[++s->top] = x;}int pop(Stack *s) {if (is_empty(s)) {printf("Error: stack underflow\n");exit(EXIT_FAILURE);}return s->data[s->top--];}int peek(Stack *s) {if (is_empty(s)) {printf("Error: stack underflow\n");exit(EXIT_FAILURE);}return s->data[s->top];}int precedence(char op) {switch (op) {case '+':case '-':return 1;case '*':case '/':return 2;default:return 0;}}int evaluate(int op1, int op2, char op) {switch (op) {case '+':return op1 + op2;case '-':return op1 - op2;case '*':return op1 * op2;case '/':return op1 / op2;default:printf("Error: invalid operator\n");exit(EXIT_FAILURE);}}int evaluate_infix(char *expr) {Stack op_stack, val_stack;init(&op_stack);init(&val_stack);while (*expr != '\0') {if (isdigit(*expr)) {int val = 0;while (isdigit(*expr)) {val = val * 10 + (*expr - '0');expr++;}push(&val_stack, val);} else if (*expr == '+' || *expr == '-' || *expr == '*' || *expr == '/') {while (!is_empty(&op_stack) && precedence(peek(&op_stack)) >= precedence(*expr)) {int op2 = pop(&val_stack);int op1 = pop(&val_stack);char op = pop(&op_stack);push(&val_stack, evaluate(op1, op2, op));}push(&op_stack, *expr);expr++;} else if (*expr == '(') {push(&op_stack, '(');expr++;} else if (*expr == ')') {while (peek(&op_stack) != '(') {int op2 = pop(&val_stack);int op1 = pop(&val_stack);char op = pop(&op_stack);push(&val_stack, evaluate(op1, op2, op));}pop(&op_stack);expr++;} else {printf("Error: invalid character\n");exit(EXIT_FAILURE);}}while (!is_empty(&op_stack)) {int op2 = pop(&val_stack);int op1 = pop(&val_stack);char op = pop(&op_stack);push(&val_stack, evaluate(op1, op2, op));}return peek(&val_stack);}int main() {char expr[100];printf("Enter infix expression: ");scanf("%[^\n]", expr);printf("Result = %d\n", evaluate_infix(expr));return 0;}下面是用栈实现后缀表达式求值的示例代码:#include <stdio.h>#include <stdlib.h>#include <ctype.h>#define MAX_STACK_SIZE 100typedef struct {int top;int data[MAX_STACK_SIZE];} Stack;void init(Stack *s) {s->top = -1;}int is_empty(Stack *s) {return s->top == -1;}int is_full(Stack *s) {return s->top == MAX_STACK_SIZE - 1;}void push(Stack *s, int x) {if (is_full(s)) {printf("Error: stack overflow\n");exit(EXIT_FAILURE);}s->data[++s->top] = x;}int pop(Stack *s) {if (is_empty(s)) {printf("Error: stack underflow\n");exit(EXIT_FAILURE);}return s->data[s->top--];}int peek(Stack *s) {if (is_empty(s)) {printf("Error: stack underflow\n");exit(EXIT_FAILURE);}return s->data[s->top];}int evaluate(int op1, int op2, char op) {switch (op) {case '+':return op1 + op2;case '-':return op1 - op2;case '*':return op1 * op2;case '/':return op1 / op2;default:printf("Error: invalid operator\n");exit(EXIT_FAILURE);}}int evaluate_postfix(char *expr) {Stack stack;init(&stack);while (*expr != '\0') {if (isdigit(*expr)) {int val = 0;while (isdigit(*expr)) {val = val * 10 + (*expr - '0');expr++;}push(&stack, val);} else if (*expr == '+' || *expr == '-' || *expr == '*' || *expr == '/') { int op2 = pop(&stack);int op1 = pop(&stack);push(&stack, evaluate(op1, op2, *expr));expr++;} else {printf("Error: invalid character\n");exit(EXIT_FAILURE);}}return peek(&stack);}int main() {char expr[100];printf("Enter postfix expression: ");scanf("%[^\n]", expr);printf("Result = %d\n", evaluate_postfix(expr));return 0;}。
前缀表达式、中缀表达式、后缀表达式的定义及实现
前缀表达式、中缀表达式、后缀表达式的定义及实现定义1. 中缀表达式:平常我们⼿动输⼊的表达式、计算式,都是中缀表达式,按照我们理解的运算优先顺序进⾏计算。
按照⼈的思维⽅式进⾏表达式的输⼊,最终输出预期结果。
⽐如 1 + (2 + 3) × 4 - 52. 后缀表达式、前缀表达式:虽然中缀表达式是按照我们⾁眼的运算符优先级写出的,但是最终实现这个运算的,⽐如计算器是没有这么智能的,计算器只会按照输⼊的运算符⼀个⼀个的进⾏计算。
这时候就⽤到了后缀、前缀表达式。
⽐如:后缀表达式针对于上⾯的就是 1 2 3 + 4 × + 5 -⼿动实现1. 那么我们怎么实现中缀转换为后缀呢?⼿动实现:把所有运算按照优先级加上括号,然后把运算符号移动到括号前⾯,然后去除括号。
⽐如: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. 进⾏后缀表达式的计算第⼀步程序思路:1. 定义栈S1,存储运算符。
定义栈S2,存储数字和运算符,存储最终的后缀表达式2. 对于新字符进⾏判断只要新字符不等于‘\0’,⼀直进⾏下⾯的循环:1. 如果S1的⼤⼩为空, 字符⼊S12. 如果是( ⼊栈3. 如果是),将S1知道(之前的运算符出栈,添加到S2中4. 如果S1的⼤⼩不为空,并且S1栈顶的运算符优先级⼤于当前的新字符或者两个字符是相等的那么当前的S1栈顶就可以出栈,添加到S2中新字符⼊栈S15. 如果新字符的范围是‘0’ - ’9‘之间,那么新字符添加进S2中6. 否则,添加到S1中3. 跳出循环后,如果S1的size不为空,把S1的运算符⼀⼀弹出,添加到S2中,最终S2就是排列好的后缀表达式4. 然后就可以进⾏运算代码,使⽤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;}4. 核⼼函数就是上⾯的两个,输⼊参数1是中缀表达式,输⼊参数2是栈,最终栈中存储排序好的后缀表达式5. 拿⼀个例⼦来演⽰⼀下:6.说明后缀表达式,这种⽅式后计算优点也很⼤,直接从上到下,数字就⼊栈,符号就把当前栈中的连续两个弹出,然后和当前符号进⾏运算,然后再⼊数字栈。
c语言中缀后缀算术表达式求值用栈实现
c语言中缀、后缀算术表达式求值用栈实现#include<stdio.h>#include<string.h>#include<malloc.h>#include<stdlib.h>#define MaxSize 50typedef struct{float data[MaxSize];int top;}OpStack;typedef struct{char data[MaxSize];int top;}SeqStack;void InitStack(SeqStack *S);//初始化栈int StackEmpty(SeqStack S);//判断栈是否为空int PushStack(SeqStack *S,char e);//进栈int PopStack(SeqStack *S,char *e);//删除栈顶元素int GetTop(SeqStack S,char *e);//取栈顶元素void TranslateExpress(char s1[],char s2[]);//将中缀表达式转化为后缀表达式float ComputeExpress(char s[]);//计算后缀表达式的值void main(){char a[MaxSize],b[MaxSize];float f;printf("请输入一个算术表达式:\n");gets(a);printf("中缀表达式为:%s\n",a);TranslateExpress(a,b);printf("后缀表达式为:%s\n",b);f=ComputeExpress(b);printf("计算结果:%f\n",f);}void InitStack(SeqStack *S)//初始化栈{S->top=0;}int StackEmpty(SeqStack S)//判断栈是否为空{if(S.top ==0)return 1;elsereturn 0;}int PushStack(SeqStack *S,char e)//进栈{if(S->top>=MaxSize){printf("栈已满,不能进栈!"); return 0;}else{S->data[S->top]=e;S->top++;return 1;}}int PopStack(SeqStack *S,char *e)//删除栈顶元素{if(S->top==0){printf("栈已空\n");return 0;}else{S->top--;*e=S->data[S->top];return 1;}}int GetTop(SeqStack S,char *e)//取栈顶元素{if(S.top<=0){printf("栈已空");return 0;}else{*e=S.data[S.top-1];return 1;}}void TranslateExpress(char str[],char exp[])//把中缀表达式转换为后缀表达式{SeqStack S;char ch;char e;int i=0,j=0;InitStack(&S);ch=str[i];i++;while(ch!='\0') //依次扫描中缀表达式{switch(ch){case'(':PushStack(&S,ch);break;case')':while(GetTop(S,&e)&&e!='('){PopStack(&S,&e);exp[j]=e;j++;}PopStack(&S,&e);break;case'+':case'-':while(!StackEmpty(S)&&GetTop(S,&e)&&e!='(') {PopStack(&S,&e);j++;}PushStack(&S,ch);break;case'*':case'/':while(!StackEmpty(S)&&GetTop(S,&e)&&e=='/'||e==&# 39;*'){PopStack(&S,&e);exp[j]=e;j++;}PushStack(&S,ch);break; //是空格就忽略case' ':break;default:while(ch>='0'&&ch<='9'){exp[j]=ch;j++;ch=str[i];i++;}i--;exp[j]=' ';j++;}ch=str[i];i++;}while(!StackEmpty(S)) //将栈中剩余运算符出栈{PopStack(&S,&e);exp[j]=e;j++;}exp[j]='\0';}float ComputeExpress(char a[])//计算后缀表达式的值{int i=0;float x1,x2,value;float result;S.top=-1;while(a[i]!='\0') //依次扫描后缀表达式{if(a[i]!=''&&a[i]>='0'&&a[i]<='9')//如果是数字{value=0;while(a[i]!=' ') //如果不是空格{value=10*value+a[i]-'0';i++;}S.top++;S.data[S.top]=value; //处理后进栈}else //如果是运算符{switch(a[i]){case'+':x1=S.data[S.top];S.top--;x2=S.data[S.top];S.top--;result=x1+x2;S.top++;S.data[S.top]=result;break;case'-':x1=S.data[S.top];S.top--;x2=S.data[S.top];S.top--;result=x2-x1;S.top++;S.data[S.top]=result;break;case'*':x1=S.data[S.top];S.top--;x2=S.data[S.top];S.top--;result=x1*x2;S.top++;S.data[S.top]=result;break;case'/':x1=S.data[S.top];S.top--;x2=S.data[S.top];S.top--;result=x2/x1;S.top++;S.data[S.top]=result;break;}i++;}}if(!S.top!=-1) //如果栈不空,将结果出栈并返回{result=S.data[S.top];S.top--;if(S.top==-1)return result;else{printf("表达式错误");exit(-1);}}return 0;}。
前缀后缀算数运算编程
一、设计思想1、中缀转化为后缀算法过程中要使用一个栈和两个数组,(栈用来存放运算符,一个数组用来存放中缀表达式,两一个则是存放后缀表达式)表达式的转换过程如下:(1)、将表达式开始符“#“压入运算符栈,作为栈底元素。
(2)、从左到右依次扫描中缀表达式的每一个字符。
(3)、如果遇到的是开括号“(”,则将它们压入一个操作符栈(不需要与栈顶操作符相比较),它表明一个新的计算层次的开始,在遇到和它匹配的闭括号“)”时,将栈中的元素弹出来并放入后缀表达式中,直到栈顶元素为“(”时,将栈顶元素“(”弹出(不需要加入后缀表达式),表明这一层括号内的操作处理完毕(4)、即将进栈的操作符要与栈顶的操作符进行优先级比较,若当所遇到的操作符的优先级大于栈顶元素时,进栈,否则是将栈顶元素一次弹栈放入后缀数组,直到比较操作符小于或等于栈顶元素时为止。
重复以上操作,最后将栈内所有操作符放进后缀数组内。
(5)、重复上述步骤直到缀表达式的结束符标记“#“,弹出栈中所有元素并放入后缀表达,转换结束。
中缀表达式为:17-3*4+(8/2)# 后缀表达式为:17 3 4 * - 8 2/+2、中缀转化为前缀算法过程中要使用三个数组,(一个栈数组,一个存放中缀表达式,一个存放前缀表达式)表达式的转换过程如下:(1)将表达式开始符“#“压入运算符栈数组,作为栈底元素。
(2)、从右到左依次扫描中缀表达式的每一个字符。
(3)、如果遇到的是开括号“)”,则将它们放进栈数组内(不需要与栈顶操作符相比较),它表明一个新的计算层次的开始,在遇到和它匹配的闭括号“(”时,将栈中的元素弹出来并放入前缀表达式中,直到栈顶元素为“)”时,将栈顶元素“)”弹出(不需要加入后缀表达式),表明这一层括号内的操作处理完毕(4)、如果遇到的是操作符,则将该操作符和操作符栈顶元素比较:当所遇到的操作符的优先级小于栈顶元素的优先级时,则取出栈顶元素放入后缀表达式,并弹出该栈顶元素,反复执行直到操作符的优先级大于或等于栈顶元素的优先级的时则将它压入栈中。
C语言计算器实现(中缀表示法后缀表示法)
C语⾔计算器实现(中缀表⽰法后缀表⽰法)————————————————————————————————————————————实现原理:每个操作数都被依次压⼊栈中,当⼀个运算符到达时,从栈中弹出相应数⽬的操作数(对于⼆元运算符来说是两个操作数),把该运算符作⽤于弹出的操作数,并把运算结果再压⼊栈中- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -计算器(后缀表达式)相关知识:后缀表达式(逆波兰表⽰法):在逆波兰中,所有运算符都跟在操作数后⾯,如下:(1 - 2) *(4 + 5) 采⽤逆波兰表⽰法表⽰为:1 2 - 4 5 + *,不需要圆括号,只要知道每个运算符需要⼏个操作数就不会引起歧义实现功能:输⼊后缀表达式,以换⾏结束,计算四则运算结果。
对于 1 2 - 4 5 + * 来说,⾸先把1和2压⼊到栈中,再⽤两者之差-1取代它们;然后将4和5压⼊到栈中,再⽤两者之和9取代它们。
最后从栈中取出栈顶的-1和9,并把它们的积-9压⼊到栈顶。
到达输⼊⾏的末尾时,把栈顶的值弹出来并打印。
伪代码:while 读⼊值不为换⾏时if 是数字压⼊栈中else if 是运算符弹出两个运算数,计算并压栈else 输⼊错误并退出end if读⼊值弹出最终结果并打印实现代码:1/* 实现功能:输⼊后缀表达式,以换⾏结束,计算四则运算结果 */2/* 这种后缀表⽰法只需要⼀个栈就可以了,遇到符号则弹运算数,但是中缀就不⼀样 */3 #include <stdio.h>4 #include <stdlib.h>5#define OK 16#define ERROR 07#define OVERFLOW -28#define STACK_INIT_SIZE 1009#define STACKINCREAMENT 1010 typedef int Status;11 typedef char SElemType;12 typedef struct13 {14 SElemType *top;15 SElemType *base;16int stacksize;17 } SqStack;18 Status InitStack(SqStack *s)19 {20 s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));21if (!s->base) exit(OVERFLOW);22 s->top = s->base;23 s->stacksize = STACK_INIT_SIZE;24return OK;25 }26 Status Push(SqStack *s, SElemType e)27 {28if (s->top - s->base == s->stacksize)29 {30 s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType)); 31if (!s->base) exit(OVERFLOW);32 s->top = s->base + s->stacksize;33 s->stacksize += STACKINCREAMENT;34 }35 s->top++;36 *(s->top) = e;37return OK;38 }39 Status Pop(SqStack *s, SElemType *e)40 {41if (s->top == s->base) exit(OVERFLOW);42 *e = *(s->top);43 s->top--;44return OK;45 }46 Status Empty(SqStack s)47 {48if (s.top - s.base == 0)49return OK;50else51return ERROR;52 }53int main()54 {55 SqStack OPND; //OPTR是运算符 OPND是运算数56char c, num1, num2;57 InitStack(&OPND);58while((c = getchar()) != '\n')59 {60switch(c)61 {62case'0':63case'1':64case'2':65case'3':66case'4':67case'5':68case'6':69case'7':70case'8':71case'9':72 Push(&OPND, c - '0');73break;74case'+':75 Pop(&OPND, &num2);76 Pop(&OPND, &num1);77 Push(&OPND, num1 + num2);78break;79case'-':80 Pop(&OPND, &num2);81 Pop(&OPND, &num1);82 Push(&OPND, num1 - num2);83break;84case'*':85 Pop(&OPND, &num2);86 Pop(&OPND, &num1);87 Push(&OPND, num1 * num2);88break;89case'/':90 Pop(&OPND, &num2);91 Pop(&OPND, &num1);92 Push(&OPND, num1 / num2);93break;94default:95break;96 }97 }98while(!Empty(OPND))99 {100 Pop(&OPND, &c);101 printf("%d ", c);102 }103return OK;104 }- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -计算器(中缀表⽰法)运算符优先级:+-*/()# +>><<<>>->><<<>>*>>>><>>/>>>><>>(<<<<<=0)>>>>0>>#<<<<<0=执⾏过程:在计算 #4+3*(5-10)/5# 时栈中的执⾏过程如下步骤输⼊字符执⾏操作OPTR OPND 1#Push(#)#24Push(4)#43+'#'<'+',Push(+)# +443Push(3)# + 4 35*'+'<'*',Push(*)# + * 4 36('*'<'(',Push(()# + * ( 4 375Push(5)# + * ( 4 3 58-'('<'-',Push(-)# + * ( - 4 3 5910Push(10)# + * ( - 4 3 5 1010)'-'>')',计算并压⼊结果# + * ( 4 3 -511'('=')',脱括号# + * 4 3 -5 12/'*'>'/'计算并压⼊结果# + 4 -1513'+'<'/',Push(/)# + / 4 -15145Push(5)# + / 4 -15 5 15#'/'>'#',计算并压⼊结果# + 4 -316'+'>'#',计算并压⼊结果#117'#'='#',脱括号1伪代码:初始化运算符栈;压⼊#;初始化运算数栈;获取输⼊;while 获取输⼊不为#或栈顶不为#if 输⼊的是数字压⼊运算数栈获取输⼊if 新输⼊的也是数字⼗位数百位数运算end ifelseswitch 运算符栈顶与当前输⼊优先级⽐较压⼊运算符栈获得输⼊弹出运算符栈顶(或#获得输⼊弹出运算符栈顶弹出两个运算数计算并将结果压⼊运算数栈//此时不获取新输⼊,该循环输⼊的运算符作为c重新进⼊循环end ifend while输出运算数栈中剩的运算数实现代码:1/* 只能运算-128~127之间的结果 */2 #include <stdio.h>3 #include <stdlib.h>4 #include <math.h>5#define OK 16#define ERROR 07#define SPILL -2 //math.h中已有OVERFLOW,则改⽤SPILL8#define STACK_INIT_SIZE 1009#define STACKINCREAMENT 1010 typedef char SElemType;11 typedef int Status;12 typedef struct13 {14 SElemType *top;15 SElemType *base;16int stacksize;17 } SqStack;18 Status InitStack(SqStack *s)19 {20 s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));21if (!s->base)22 exit(SPILL);23 s->top = s->base;24 s->stacksize = STACK_INIT_SIZE;25return OK;26 }27 Status EmptyStack(SqStack s)28 {29if (s.top - s.base == 0)30return OK;31else32return ERROR;33 }34 Status Push(SqStack *s, SElemType e)35 {36if (s->top - s->base == s->stacksize)37 {38 s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType)); 39if (!s->base)40 exit(SPILL);41 s->top = s->base + s->stacksize;42 s->stacksize += STACKINCREAMENT;43 }44 s->top ++;45 *(s->top) = e;46return OK;47 }48 Status Pop(SqStack *s, SElemType *e)49 {50if (s->top == s->base)51 exit(SPILL);52 *e = *(s->top);53 s->top--;54return OK;55 }56 SElemType GetTop(SqStack s)57 {58return *(s.top);59// *e = *(s.top);60// return OK;61 }62/* 判断如果是数字则返回OK,运算符返回ERROR,⾮法输⼊则退出 */63 Status InputJudge(SElemType c)64 {65switch(c)66 {67case'0':68case'1':69case'2':70case'3':71case'4':72case'5':73case'6':74case'7':75case'8':76case'9':77return OK;78break;79case'+':80case'-':81case'*':82case'/':83case'(':84case')':85case'#':86return ERROR;87break;88default:89 exit(SPILL);90break;91 }92 }93/* 当前输⼊的运算符和前⼀个运算符⽐较优先级 */94 SElemType PriorityJudge(SElemType optr1, SElemType optr2)95 {96int i, j;97char priorityTable[7][7] =98 {99 {'>', '>', '<', '<', '<', '>', '>'},100 {'>', '>', '<', '<', '<', '>', '>'},101 {'>', '>', '>', '>', '<', '>', '>'},102 {'>', '>', '>', '>', '<', '>', '>'},103 {'<', '<', '<', '<', '<', '=', '0'},104 {'>', '>', '>', '>', '0', '>', '>'},105 {'<', '<', '<', '<', '<', '0', '='}106 };107switch(optr1)108 {109case'+':110 i = 0;111break;112case'-':113 i = 1;114break;115case'*':116 i = 2;117break;118case'/':119 i = 3;120break;121case'(':122 i = 4;123break;124case')':125 i = 5;126break;127case'#':128 i = 6;129break;130 }131switch(optr2)132 {133case'+':134 j = 0;135break;136case'-':137 j = 1;138break;139case'*':140 j = 2;141break;142case'/':143 j = 3;144break;145case'(':146 j = 4;147break;148case')':149 j = 5;150break;151case'#':152 j = 6;153break;154 }155return priorityTable[i][j];156 }157/* 四则运算 */158 SElemType Calc(SElemType optr, SElemType num1, SElemType num2)159 {160switch(optr)161 {162case'+':163return (num1 + num2);164break;165case'-':166return (num1 - num2);167break;168case'*':169return (num1 * num2);170break;171case'/':172return (num1 / num2);173break;174 }175 }176int main()177 {178char c, optr, num1, num2, temp;179 SqStack OPND, OPTR;180 InitStack(&OPTR);181 Push(&OPTR, '#');182 InitStack(&OPND);183 c = getchar();184while(c != '#' || GetTop(OPTR) != '#')185// while(!EmptyStack(OPTR))186//严蔚敏⽼师书上的算法是判断输⼊⾮#或栈顶⾮#时循环,个⼈认为判断运算符栈不为空也可以,当初始化时压⼊的#闭合,结束运算187 {188if (InputJudge(c))189 {190 Push(&OPND, c - '0');191 c = getchar();192/* 当连续输⼊数字时,计算⼗位数和百位数 */193while(InputJudge(c))194 {195int i = 1;196 Pop(&OPND, &temp);197 Push(&OPND, temp * pow(10, i) + (c - '0'));198 i++;199 c = getchar();200 }201 }202else203switch(PriorityJudge(GetTop(OPTR), c))204 {205case'<':206 Push(&OPTR, c);207 c = getchar();208break;209case'=':210 Pop(&OPTR, &c);211 c = getchar();212break;213case'>':214 Pop(&OPTR, &optr);215 Pop(&OPND, &num2);216 Pop(&OPND, &num1);217 Push(&OPND, Calc(optr, num1, num2)); 218break;219 }220 }221while(!EmptyStack(OPND))222 {223 Pop(&OPND, &c);224 printf("%d\n", c);225 }226return OK;227 }。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
c语言实现中缀,后缀,前缀表达式转换并求值c语言实现中缀,后缀,前缀表达式转换并求值九#include #include #define MAXNUM 100 typedef struct Node//定义存储中缀表达式的结点类型{int data; int data1; char data2; struct Node *next; }Lnode; typedef struct Node2//定义存储前缀表达式的结点类型{int data; int data1; char data2; struct Node2 *next; struct Node2 *prior; }Lnode2; typedef int selemtype1;//定义运算数栈的结点typedef struct//定义运算数栈的类型{selemtype1 *base; selemtype1 *top; }sqstack1; void InitStack1(sqstack1 &s)//新建一个空运算数栈{=(selemtype1 *)malloc(MAXNUM*sizeof(selemtype1));=; if(!) printf(“出错:申请空间失败!\\n”); } void Push1(sqstack1 &s,selemtype1 &e)//运算数栈,入栈:插入元素e为新的栈顶元素{ if(>=MAXNUM) printf(“出错:表达式过长!1\\n”); *++ =e; } void GetTop1(sqstack1 s,selemtype1 &e)//运算数栈,用e返回栈顶元素{e=*(); } void Popopnd1(sqstack1 &s,selemtype1 &e) //运算数栈,退栈:删除栈顶元素,并用e返回其值{e=*--; } int stackempy1(sqstack1 s) //运算数栈,若为空栈返回1,否则返回0 {if(==) return 1; else return 0; } typedef char selemtype2;//定义运算符栈的结点类型typedef struct//定义运算符栈类型{selemtype2 *base; selemtype2 *top; }sqstack2; void InitStack2(sqstack2 &s)//新建一个空运算符栈{=(selemtype2 *)malloc(MAXNUM*sizeof(selemtype2)); =; if(!) printf(“出错:申请空间失败!\\n”); } void Push2(sqstack2 &s,selemtype2 &e)//运算符栈,入栈:插入元素e为新的栈顶元素{ if(>=MAXNUM) printf(“出错:表达式过长!2\\n”); *++ =e; } void GetTop2(sqstack2 s,selemtype2 &e)//运算符栈,用e返回栈顶元素{e=*(); } void Popopnd2(sqstack2 &s,selemtype2 &e) //运算符栈,退栈:删除栈顶元素,并用e返回其值{e=*--; } int stackempy2(sqstack2 s) //运算符栈,若为空栈返回1,否则返回0 {if(==) return 1; else return 0; } void priority(char c,int &i)//确定运算符优先级{if (c==‘*’||c==‘/’||c==‘%’) i=2 ; else if (c==‘+’||c==‘-’) i=1 ; else i=0; } int compare(char a,char b)//比较栈顶元素运算符与外部运算符优先级大小,外部优先级大则返回1,反之返回0 {int in,out; priority(a,in); priority(b,out); if(out>in) return 1; else return 0; } void Operat(sqstack1 &OPND,sqstack2&OPTR) {int num1,num2,num; char c; Popopnd1(OPND,num2);Popopnd1(OPND,num1);Popopnd2(OPTR,c); switch(c) {case ‘+’:num=num1+num2;break; case ‘-’:num=num1-num2;break; case ‘*’:num=num1*num2;break; case ‘/’:num=num1/num2;break; case ‘%’:num=num1%num2;break; } Push1(OPND,num); } void Operatqianzhui(sqstack1 &OPND,sqstack2 &OPTR) {int num1,num2,num; char c; Popopnd1(OPND,num1);Popopnd1(OPND,num2);Popopnd2(OPTR,c); switch(c) {case ‘+’:num=num1+num2;break; case ‘-’:num=num1-num2;break; case ‘*’:num=num1*num2;break; case ‘/’:num=num1/num2;break; case ‘%’:num=num1%num2;break; } Push1(OPND,num); }voidhouzhuiqiuzhi(Lnode *p,int &e) {sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n; char c; p=p->next; InitStack1(OPND); InitStack2(OPTR); while(p) {switch(p->data) {case 1:n=p->data1; Push1(OPND,n); break; case 2:c=p->data2; Push2(OPTR,c); Operat(OPND,OPTR); break; default:printf(“结点有误”); brea k; } p=p->next; } Popopnd1(OPND,n); e=n; } void zhongzhui(Lnode *p) {sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n; //后缀表达式求值//中缀表达式求值char c,c2; Lnode *first; first=p; p=p->next; InitStack1(OPND); InitStack2(OPTR); while(!stackempy2(OPTR)||p) {while(p) {switch(p->data) {case 1:n=p->data1; Push1(OPND,n); break; case 2:c=p->data2; if(stackempy2(OPTR)) Push2(OPTR,c); else { switch(c){case ‘(‘: Push2(OPTR,c);break; case ‘)’: GetTop2(OPTR,c2); while(c2!=‘(‘) {Operat(OPND,OPTR);GetTop2(OPTR,c2);}Popopnd2(OPTR,c2); break; default: GetTop2(OPTR,c2);if(compare(c2,c)) Push2(OPTR,c); else { Operat(OPND,OPTR); Push2(OPTR,c); } break; } } break; default: printf(“结点有误”); break; } p=p->next; } while(!stackempy2(OPTR))Operat(OPND,OPTR); } Popopnd1(OPND,n); p=first->next; while(p) {if(p->data==1) printf(“%d “,p->data1); if(p->data==2) printf(“%c”,p->data2);p=p->next; } printf(“=%d “,n); }void houzhui(Lnode *p)//中缀表达式转化为后缀表达式{sqstack2OPTR; //运算符栈Lnode *r,*q,*head; int n; char c,c2; InitStack2(OPTR); p=p->next;q=(Lnode*)malloc(sizeof(struct Node)); head=q; while(p) { switch(p->data) {case 1:n=p->data1; r=(Lnode*)malloc(sizeof(struct Node)); q->next=r; q=q->next; q->data=1; q->data1=n; break; case 2:c=p->data2; if(stackempy2(OPTR)) Push2(OPTR,c); else { switch(c) { case ‘(‘: Push2(OPTR,c);break; case ‘)’: Popopnd2(OPTR,c2); while(c2!=‘(‘) { r=(Lnode*)malloc(sizeof(struct Node)); q->next=r; q=q->next; q->data=2; q->data2=c2; Popopnd2(OPTR,c2); } break; default: GetTop2(OPTR,c2); while(!compare(c2,c)){ Popopnd2(OPTR,c2); r=(Lnode*)malloc(sizeof(struct Node)); q->next=r; q=q->next; q->data=2; q->data2=c2; GetTop2(OPTR,c2); }Push2(OPTR,c); break; } } break; default: printf(“结点有误”); break; } p=p->next; } while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2); r=(Lnode*)malloc(sizeof(struct Node)); q->next=r; q=q->next; q->data=2; q->data2=c2; } q->next=NULL; q=head->next; while(q) {if(q->data==1) printf(“%d “,q->data1); if(q->data==2) printf(“%c”,q->data2); q=q->next; } houzhuiqiuzhi(head,n); printf(“=%d “,n); } void qianzhuiqiuzhi(Lnode2 *p,int &e) //前缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n; char c; Lnode2 *head; head=p; p=p->next; InitStack1(OPND); InitStack2(OPTR); while(p!=head) {switch(p->data) {case 1:n=p->data1; Push1(OPND,n); break; case 2:c=p->data2; Push2(OPTR,c);Operatqianzhui(OPND,OPTR); break; default:printf(“结点有误”); break; } p=p->next; } Popopnd1(OPND,n); e=n; }void qianzhui(Lnode *p)式{sqstack2 OPTR; //运算符栈InitStack2(OPTR); int n; char c,c2; Lnode *first; Lnode2 *q,*head,*r,*head2,*s; first=p; p=p->next; q=(Lnode2*)malloc(sizeof(struct Node2)); //中缀表达式转化为前缀表达//建立存中缀表达式的双向循环链表head=q; while(p) {r=(Lnode2*)malloc(sizeof(struct Node2)); q->next=r; r->prior=q; q=q->next; q->data=p->data; q->data1=p->data1; q->data2=p->data2; p=p->next; } q->next=head; head->prior=q; s=(Lnode2*)malloc(sizeof(struct Node2)); //建立存前缀表达式的双向循环链表head2=s; while(q!=head) {switch(q->data) {case 1:n=q->data1; r=(Lnode2*)malloc(sizeof(struct Node2)); s->next=r; r->prior=s; s=s->next; s->data=1; s->data1=n; break; case 2:c=q->data2; if(stackempy2(OPTR)) Push2(OPTR,c); else { GetTop2(OPTR,c2); if(c2==‘)’) Push2(OPTR,c); else{ switch(c) { case ‘)’:Push2(OPTR,c);break; case ‘(‘: Popopnd2(OPTR,c2); while(c2!=‘)’) { r=(Lnode2*)malloc(sizeof(struct Node2)); s->next=r; r->prior=s; s=s->next; s->data=2; s->data2=c2; Popopnd2(OPTR,c2); } break; default: GetTop2(OPTR,c2); while(!compare(c2,c)){ Popopnd2(OPTR,c2); r=(Lnode2*)malloc(sizeof(struct Node2)); s->next=r; r->prior=s; s=s->next; s->data=2; s->data2=c2; GetTop2(OPTR,c2); } Push2(OPTR,c); break; } } } break; default:printf(“结点有误”); break; }q=q->prior; } while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2); r=(Lnode2*)malloc(sizeof(struct Node2)); s->next=r; r->prior=s; s=s->next; s->data=2; s->data2=c2; } s->next=head2; head2->prior=s; while(s!=head2) {if(s->data==1) printf(“%d “,s->data1);if(s->data==2) printf(“%c”,s->data2); s=s->prior; } qianzhuiqiuzhi(head2,n); printf(“=%d “,n);}int main() { char n[10]; char c; int i,j,k,a,b,z,y,e; Lnode *p,*q,*first; i=0;e=1;a=0;b=1;z=0;y=0;p=(Lnode*)malloc(sizeof(struct Node)); first=p; printf(“请输入中缀表达式”); do { c = getchar(); if(‘0’{ switch (c) { case ‘+’: case ‘-’: case ‘*’: case ‘/’: case ‘%’: case ‘(‘:case ‘)’: case ‘\\n’: { if(n[0]>‘0’&&n[0]next=q; p=p->next; for(k=0;k{ for(j=0;j a=a+(n[k]-’0’)*e; e=1; n[k]=‘0’; } p->data=1; p->data1=a; i=0;a=0; } if(c!=‘\\n’) { if(p->data==2) { if(p->data2!=‘)’&&c!=‘(‘) b=0; } q=(Lnode*)malloc(sizeof(struct Node)); p->next=q; p=p->next; p->data=2; p->data2=c; if(c==‘(‘) z++; if(c==‘)’) y++; } } default: if(c!=‘+’&&c!=‘-’&&c!=‘*’&&c!=‘/’&& c!=‘%’&&c!=‘\\n’&&c!=‘(‘&&c!=‘)’)b=0; } } }while (c != ‘\\n’); if(z!=y) b=0; p->next=NULL; if(b==0) printf(“输入中缀表达式有误”); else {printf(“输入1中缀表达式求值,输入2后缀表达式求值,输入3前缀表达式求值”); scanf(“%d”,&b); if(b==1) zhongzhui(first); if(b==2) houzhui(first); if(b==3) qianzhui(first); } return 1; }。