基于栈结构的中缀表达式求值
c++ 中缀表达式

c++ 中缀表达式
C++ 中缀表达式(Infix Expression)是指运算符位于操作数之
间的表达式,例如:a + b * c。
在C++中,中缀表达式的求值需要遵循运算符的优先级和结
合性规则。
一般来说,乘法、除法、取模运算的优先级最高,加法、减法运算的优先级较低。
在编写C++程序时,为了正确求解中缀表达式,可以使用以
下方法之一:
1. 使用栈进行中缀表达式的转换和求解。
2. 使用递归函数或逆波兰表达式将中缀表达式转换成后缀表达式,然后使用栈进行后缀表达式的求解。
例如,给定中缀表达式 a + b * c,可以使用栈的方法求解:
1. 创建一个空栈用于存储运算符和操作数。
2. 遍历中缀表达式的每个字符,按以下规则处理:
- 如果遇到操作数,则将其压入栈中。
- 如果遇到运算符,则根据其优先级和结合性,判断是否需
要将运算符从栈中弹出并进行运算。
然后将运算结果压入栈中。
- 如果遇到左括号,则直接将其压入栈中。
- 如果遇到右括号,则取出栈中的运算符和操作数,直到遇
到左括号为止,并进行相应的运算。
最后将运算结果压入栈中。
3. 遍历完中缀表达式后,栈中最后一个元素即为表达式的结果。
注:以上只是一种求解中缀表达式的方法,实际求解方法可能有其他的实现方式。
表达式求值算法总结(C++)

表达式求值算法总结(C++)表达式求值,一般采用栈和队列的方式来求值,下面介绍表达式求值的两种算法。
方法一、使用两个栈,一个为操作符栈OPTR(operator),一个是操作数栈OPND(operand)算法过程:当输入3 * ( 4 - 1 * 2 ) + 6 / ( 1 + 1 )时,为简单方便,我们输入时,按照字符的顺序一个一个的处理,比如ch = getchar()。
然后根据ch 的值判断:若ch 是数字,直接压入操作数栈OPND;若ch 是'(',直接入栈OPTR;若ch 是')',若OPTR 和OPND 非空,弹出OPTR的栈顶操作符,弹出OPND栈顶的两个操作数,做运算,然后见个结果压入栈OPND,直到弹出的OPTR栈顶元素时')';若ch 是操作符(比如+, -, *, /),如果OPTR栈顶元素是(,直接入栈OPTR,如果不是'('且OPTR栈非空且栈顶元素操作符的优先级大于ch,那么弹出OPTR的栈顶操作符,并弹出OPND中栈顶的两个元素,做运算,将运算结果入栈OPND,此时,重复这一步操作;否则将ch入栈OPTR;若ch为EOF,说明表达式已经输入完成,判断OPTR是否为空,若非空,一次弹出OPTR 栈顶操作符,并与OPND栈顶两个元素做运算,将运算结果入栈OPND,最后表达式的结果即OPND的栈底元素。
以表达式3 * ( 4 - 1 * 2 ) + 6 / ( 1 + 1 )为例,计算过程如下所示:通过上述的计算过程,写出伪代码如下所示:void GetExpress(Stack * OPTR, Stack * OPND){char ch;while ((ch = getchar ()) != EOF) {if (IsDigit (ch)) {PushStack (OPND, ch);}else if (ch == '(')PushStack (OPTR, ch);else if (ch == ')') {while (!IsStackEmpty(OPTR)) {PopStack (OPTR, op);if (op == ')')break;PopStack (OPND, num2);PopStack (OPND, num1);res = Calc (num1, num2, op);PushStack (OPND, res);}}else if (ch == '+' || ch == '-'|| ch == '*' || ch == '/') {while (!IsStackEmpty (OPTR) && GetTop (OPTR)!='(' && GetTop (OPTR)>ch) { PopStack (OPTR, op);PopStack (OPND, num2);PopStack (OPND, num1);res = Calc (num1, num2, op);PushStack (OPND, res);}if (IsStackEmpty (OPTR) || GetTop(OPTR)=='(')PushStack (OPTR, ch);}}}// 当表达式输入完成后,需要对OPTR栈和OPND中的元素进行运算int GetValue(Stack * OPTR, Stack * OPND){while (!IsStackEmpty (OPTR)) {PopStack (OPTR, op);PopStack (OPND, num2);PopStack (OPND, num1);res = Calc (num1, num2, op);PushStack (OPND, res);}// 最后的操作数栈OPND栈顶元素即是表达式的值return GetTop(OPND);}PS: 上面没有指出表达式非法的情况方法二:采用中缀表达式的方法,求取表达式的中缀表达式,借用一个操作符栈OPTR和中缀表达式队列Queue,求取中缀表达式,然后对中缀表达式求值。
C语言数据结构之栈:中缀表达式的计算

C语⾔数据结构之栈:中缀表达式的计算*注:本⼈技术不咋的,就是拿代码出来和⼤家看看,代码漏洞百出,完全没有优化,主要看⽓质,是吧学了数据结构——栈,当然少不了习题。
习题中最难的也是最有意思的就是这个中缀表达式的计算了(可以算+-*/和^,当然也可以带⼩括号)。
搞了很久很久啊,终于搞出来的。
简单说⼀下程序原理:因为中缀表达式基本没法算(就算可以也肯定会超时),所以得把中缀表达式转为后缀表达式。
程序分为两步第⼀步:将中缀表达式转为后缀表达式创建⼀个字符串,⽐如叫get,⽤于存储后缀表达式先是输⼊⼀个字符串,逐⼀读取单个字符,当是数字则直接存⼊get,如果是操作符则:创建栈,⽐如叫chaswhile循环当栈顶操作符优先级⼤于或等于当前操作符则弹出并把栈顶元素赋值给get 直到发现优先级⼩于当前操作符的栈顶的操作符,⼩于当前操作符的那个栈顶操作符不弹出然后将当前操作符压⼊栈内当当前操作符为'('则直接压⼊栈内当当前操作符为')'则while循环弹出栈顶操作符并赋值给get直到弹出的是'(' ( '('只弹出不赋值)注意,')'不压⼊栈中第⼆部:计算get创建int型数组栈,⽐如ints逐个读⼊get当读到数字压⼊ints当读到操作符则弹出两个ints的栈顶元素,并进⾏相应计算,将计算得到的值压⼊栈ints中最后读完get时,ints数组只剩下⼀个元素了,输出。
⾃个⼉写的稀巴烂源码(c):1 #include <stdio.h>2 #include <string.h>3 #include <math.h>45int ints[10000];6int intt;//ints的top7char chas[10000];8int chat;//chas的top9int i=0, ii=1;10char c;11char get[10000];//输⼊的中缀表达式12char get2[10000];//计算得出的后缀表达式1314void intpush(x)//整型栈压栈15 {16 intt++; ints[intt]=x;17 }18void chapush(x)//字符型栈压栈19 {20 chat++; chas[chat]=x;21 }22int intpop()//整型栈弹出23 {24 intt--; return ints[intt+1];25 }26char chapop()//字符型栈弹出27 {28 chat--; return chas[chat+1];29 }30void intadd(int x)//整型栈栈顶元素加⼊新的个位数字32 ints[intt]*=10; ints[intt]+=x;33 }3435int find()//get2加⼊操作符36 {37 c=chapop();38 get2[ii]='';39 get2[ii+1]=c;40 ii+=2;41if(chat==0) return0;42return1;43 }4445int main()46 {47 intt=0; chat=0;48 gets(get);49int lengets=strlen(get);50for(i=0;i<=lengets-1;i++)//逐个读取输⼊的中缀表达式51 {52if (isdigit(get[i]))//当get[i]为数字时53 {54 get2[ii]=get[i];55 ii++;56 }57else58 {59if(get[i]=='(')chapush('(');60if(get[i]=='^')chapush('^');61if(get[i]==')')62 {63 c=chapop();64while(c!='(')65 {66 get2[ii]='';67 get2[ii+1]=c;68 ii+=2;69 c=chapop();70 }71 }72if(get[i]=='+')73 {74while(chas[chat]=='+'||chas[chat]=='-'||chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^') 75 {76if(find()==0)break;77 }78 chapush('+');79 }80if(get[i]=='-')81 {82while(chas[chat]=='+'||chas[chat]=='-'||chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^') 83 {84if(find()==0)break;85 }86 chapush('-');87 }88if(get[i]=='*')89 {90while(chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')91 {92if(find()==0)break;93 }94 chapush('*');95 }96if(get[i]=='/')97 {98while(chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')99 {100if(find()==0)break;101 }102 chapush('/');103 }104 get2[ii]='';105 ii++;106 }107108 }109while(chat>0)//输出栈内剩余的操作符110 {111int c=chapop();112 get2[ii]='';113 get2[ii+1]=c;114 ii+=2;116 get2[ii]='@';//加⼊结束符117 i=1;118while(get2[i]!='@')//当看到结束符停⽌计算119 {120if(get2[i]=='+'||get2[i]=='-'||get2[i]=='*'||get2[i]=='/'||get2[i]=='^')121 {122int a=intpop();int b=intpop();int c;123if(get2[i]=='+') c=a+b;124if(get2[i]=='-') c=b-a;125if(get2[i]=='*') c=a*b;126if(get2[i]=='/') c=b/a;127if(get2[i]=='^') c=pow(b,a);128 intpush(c);129 }130else131 {132if(get2[i]!='')133 {134 intpush(get2[i]-48);135 ii=1;136while(get2[i+ii]!='')137 {138 intadd(get2[i+ii]-48);139 ii++;140 }141 i+=ii-1;142 }143 }144 i++;145 }146 printf("%d",ints[1]);147return0;148 }样例输⼊:1+(3+2)*(7^2+6*9)/(2)样例输出:258好了,就写到这了。
利用栈来实现算术表达式求值的算法

利用栈来实现算术表达式求值的算法利用栈来实现算术表达式求值的算法算术表达式是指按照一定规则组成的运算式,包含数字、运算符和括号。
在计算机中,求解算术表达式是一项基本的数学运算任务。
根据算术表达式的性质,我们可以考虑利用栈这一数据结构来实现求值算法。
一、算法思路首先,我们需要明确一个重要概念——逆波兰表达式(ReversePolish notation)。
逆波兰表达式是一种没有括号的算术表达式,其运算规则是先计算后面的数字和运算符,再计算前面的数字和运算符。
例如,对于算术表达式“3+4*5-6”,其对应的逆波兰表达式为“3 45 * +6 -”。
那么,我们可以利用栈来实现将中缀表达式转化为逆波兰表达式的过程,具体步骤如下:1. 创建两个栈——操作数栈和操作符栈。
2. 从左到右扫描中缀表达式的每一个数字和运算符,遇到数字则压入操作数栈中,遇到运算符则进行如下操作:(1)如果操作符栈为空或当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符压入操作符栈中。
(2)如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符弹出并加入操作数栈中,重复此过程直到遇到优先级较低的运算符或操作符栈为空为止,然后将当前运算符压入操作符栈中。
3. 扫描完中缀表达式后,若操作符栈不为空,则将其中所有运算符弹出并加入操作数栈中。
4. 最终,操作数栈中存放的就是逆波兰表达式,我们可以按照逆波兰表达式的计算规则来计算其结果。
二、算法优点利用栈来实现算术表达式求值的算法具有以下优点:1. 代码简洁易懂,易于实现和维护。
2. 由于将中缀表达式转化为逆波兰表达式后,可以减少运算符的优先级关系而消除括号,从而减少求值的复杂度,提高程序的执行效率。
三、代码实现下面是利用栈来实现算术表达式求值的算法的Python代码实现:```pythonclass Stack:def __init__(self):self.items = []def push(self, item):self.items.append(item)def pop(self):return self.items.pop()def peek(self):return self.items[-1]def is_empty(self):return len(self.items) == 0def size(self):return len(self.items)def calculate(op_num1, op_num2, operator):if operator == "+":return op_num1 + op_num2elif operator == "-":return op_num1 - op_num2elif operator == "*":return op_num1 * op_num2elif operator == "/":return op_num1 / op_num2def infix_to_postfix(infix_expr):opstack = Stack()postfix_expr = []prec = {"+": 1, "-": 1, "*": 2, "/": 2, "(": 0} token_list = infix_expr.split()for token in token_list:if token.isdigit():postfix_expr.append(token)elif token == '(':opstack.push(token)elif token == ')':top_token = opstack.pop()while top_token != '(':postfix_expr.append(top_token)top_token = opstack.pop()else:while (not opstack.is_empty()) and(prec[opstack.peek()] >= prec[token]):postfix_expr.append(opstack.pop())opstack.push(token)while not opstack.is_empty():postfix_expr.append(opstack.pop())return " ".join(postfix_expr)def postfix_eval(postfix_expr):opstack = Stack()token_list = postfix_expr.split()for token in token_list:if token.isdigit():opstack.push(int(token))else:op_num2 = opstack.pop()op_num1 = opstack.pop()result = calculate(op_num1, op_num2, token) opstack.push(result)return opstack.pop()infix_expr = "3 + 4 * 5 - 6"postfix_expr = infix_to_postfix(infix_expr)print(postfix_expr)print(postfix_eval(postfix_expr))```四、总结算术表达式求值是一项常见的数学运算任务,利用栈这一数据结构来实现求值算法是一种简单有效的方法,它将中缀表达式转化为逆波兰表达式后,可以消除括号并减少运算符的优先级关系,从而提高程序的执行效率。
数据结构表达式求值(中缀)实验报告

数据结构表达式求值(中缀)实验报告题目名称表达式求值学号姓名指导教师日期一1. 问题描述:在计算机中,算术表达式由常量、变量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行,在程序设计时,借助栈实现。
2. 表达式求值这个程序,主要利用栈和数组,把运算的先后步骤进行分析并实现简单的运算,以字符列的形式从终端输入语法的正确的、不含变量的整数表达式。
利用已知的算符优先关系,实现对算术四则运算的求值,在求值中运用栈、运算栈、输入字符和主要操作的变化过程。
该程序相当于一个简单的计算机计算程序,只进行简单的加减乘除和带括号的四则运算。
1、基本思想(中缀表达式求值)要把一个表达式翻译成正确求值的一个机器指令序列,或者直接对表达式求值,首先要能够正确解释表达式,要了解算术四则运算的规则即:(1)先乘除后加减;(2)从左到右计算;(3)先括号内,后括号外。
下表定义的运算符之间的关系:b + - * / () # a+ > > < < < > > _ > > < < < > > * > > > > < > > / > > > > < > > ( < < < < < = ) > > > > > > # < < < < < =为了实现运算符有限算法,在程序中使用了两个工作栈。
分别是:运算符栈OPTR,操作数栈OPND.基本思想:(1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素;(2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈得栈顶运算符比较优先级后作相应操作。
基于栈结构的中缀表达式求值

实验三基于栈结构的中缀表达式求值班级:计科131、问题描述从键盘输入一中缀表达式字符串,读字符串,利用栈结构实现表达式求值。
2、输入与输出输入:从键盘中缀表达式如: 32+5×(6-4)输出:计算结果423、需求分析1.定义两个栈结构,数栈用于存放表达式中的数,符号栈用于存放表达式中的符号,实现栈的运算2.在读数的时候考虑多位运算3.实现表达式求值4、开发工具与环境硬件设备:微型计算机系统软件环境:操作系统Windows,开发工具等等5、概要设计1.结构定义typedef struct /* 运算符栈 */{ char *base,*top;int stacksize;}SqStack;typedef struct /* 运算数栈 */{ int *base,*top;int stacksize;}SqStack1;int priority[7][7]={{'>', '>', '<', '<', '<', '>', '>'}, // +{'>', '>', '<', '<', '<', '>', '>'}, // -{'>', '>', '>', '>', '<', '>', '>'}, // *{'>', '>', '>', '>', '<', '>', '>'}, // /{'<', '<', '<', '<', '<', '=', }, // ({'>', '>', '>', '>', ' ', '>', '>'}, // ){'<', '<', '<', '<', '<', ' ', '='} // #};/*用于比较符号优先级的全局二维数组*/2.各函数模块void InitStack(SqStack *s);操作结果:初始化运算符栈。
表达式求值算法

表达式求值算法表达式求值算法是计算机科学中的重要概念之一,用于计算数学表达式的结果。
在编程语言中,表达式求值是一项基本的操作,并且经常在计算过程中需要用到。
本文将介绍一些常见的表达式求值算法及其实现。
1. 逆波兰表达式法逆波兰表达式法是一种用于计算数学表达式的算法,它使用后缀表达式(也称为逆波兰表达式)来表示表达式。
逆波兰表达式是将操作符放在操作数之后的一种表示方法。
对于任意一个数学表达式,都可以通过将中缀表达式转换为后缀表达式,然后使用栈结构计算得到结果。
逆波兰表达式法的优点是计算顺序明确,不需要考虑运算符的优先级和括号的处理。
2. 中缀表达式转后缀表达式法中缀表达式是我们常见的数学表达式,如 3 + 4 * 5。
在中缀表达式中,操作符的优先级和括号起着很大的作用。
为了将中缀表达式转换为后缀表达式,我们需要使用到栈结构。
具体的算法如下:- 遍历中缀表达式的每个元素。
- 如果是操作数,则直接输出。
- 如果是操作符,则判断其与栈顶操作符的优先级,决定是否将其压入栈。
- 如果是左括号,则直接压入栈。
- 如果是右括号,则依次弹出栈顶操作符,并输出,直到遇到左括号为止。
- 遍历完表达式后,如果栈不为空,则依次弹出栈顶操作符,并输出。
3. 后缀表达式求值法后缀表达式(逆波兰表达式)的求值方法相对简单。
我们可以使用栈结构来计算后缀表达式的结果。
具体的算法如下:- 遍历后缀表达式的每个元素。
- 如果是操作数,则将其压入栈。
- 如果是操作符,则弹出栈顶的两个操作数,执行相应的计算,并将结果压入栈。
- 遍历完后缀表达式后,栈中最后剩下的元素即为计算结果。
4. 二叉树表示法除了逆波兰表达式法和中缀表达式法,我们还可以使用二叉树来表示表达式,并通过遍历二叉树来计算表达式的结果。
具体的算法如下:- 构建二叉树,将表达式的操作符作为根节点,将操作数作为叶节点。
- 通过后序遍历二叉树,计算出每个子树的值,并将结果返回给其父节点。
数据结构表达式求值实验报告-无删减范文

数据结构表达式求值实验报告数据结构表达式求值实验报告1. 引言表达式求值是计算机科学中的一个重要问题,也是数据结构的一个经典应用。
通过将中缀表达式转换为后缀表达式,并利用栈这一数据结构,可以实现对表达式的有效求值。
本实验旨在探究数据结构在表达式求值中的应用。
2. 实验内容本实验中,我们将实现一个表达式求值的程序。
具体步骤如下:1. 将中缀表达式转换为后缀表达式。
2. 使用栈来求解后缀表达式。
3. 算法原理3.1 中缀表达式转后缀表达式中缀表达式是我们常见的数学表达式,如 2 + 3 4。
而后缀表达式是将操作符放在操作数后面的表达式,上述中缀表达式的后缀表达式为 2 3 4 +。
中缀表达式到后缀表达式的转换可以通过以下步骤完成:1. 初始化一个栈和一个输出队列。
2. 从左到右遍历中缀表达式的每个字符。
3. 如果当前字符是数字,将其加入输出队列。
4. 如果当前字符是左括号,将其压入栈。
5. 如果当前字符是右括号,将栈中的操作符依次弹出并加入输出队列,直到遇到左括号为止。
6. 如果当前字符是操作符,将其与栈顶操作符进行比较:1. 如果栈为空,或者栈顶操作符为左括号,直接将当前操作符压入栈。
2. 否则,比较当前操作符与栈顶操作符的优先级,如果当前操作符的优先级较低,将栈顶操作符弹出并加入输出队列,然后将当前操作符压入栈。
3. 如果当前操作符的优先级大于等于栈顶操作符的优先级,则直接将当前操作符压入栈。
7. 遍历完中缀表达式后,将栈中的操作符依次弹出并加入输出队列。
3.2 后缀表达式求值通过将中缀表达式转换为后缀表达式,我们可以利用栈来对后缀表达式进行求值。
具体求值操作如下:1. 初始化一个栈。
2. 从左到右遍历后缀表达式的每个字符。
3. 如果当前字符是数字,将其加入栈。
4. 如果当前字符是操作符,从栈中弹出两个数字,进行相应的运算,然后将结果加入栈。
5. 遍历完后缀表达式后,栈中的元素即为最终的结果。
4. 实验结果我们用中缀表达式\。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验3:栈与队列实验——基于栈结构的中缀表达式求值一、问题描述从键盘输入任意中缀表达式字符串,读字符串,利用栈结构实现表达式求值。
二、输入与输出输入:从键盘中缀表达式如: 32+5×(6-4)输出:计算结果42三、需求分析1.定义两个栈结构,数栈用于存放表达式中的数,符号栈用于存放表达式中的符号,实现栈的运算2.在读数的时候考虑多位运算3.实现表达式求值四、开发工具与环境硬件设备:微型计算机系统软件环境:操作系统Windows开发工具:Devc++五、概要设计参考结构定义typedef struct /* 运算符栈 */{ char *base,*top;int stacksize;}SqStack;typedef struct /* 运算数栈 */{ int *base,*top;int stacksize;}SqStack1;int priority[7][7]={{'>', '>', '<', '<', '<', '>', '>'}, // +{'>', '>', '<', '<', '<', '>', '>'}, // -{'>', '>', '>', '>', '<', '>', '>'}, // * {'>', '>', '>', '>', '<', '>', '>'}, // / {'<', '<', '<', '<', '<', '=', ' '}, // ( {'>', '>', '>', '>', ' ', '>', '>'}, // ) {'<', '<', '<', '<', '<', ' ', '='} // # };/*用于比较符号优先级的全局二维数组*/2.各函数模块void InitStack(SqStack *s);操作结果:初始化运算符栈char GetTop(SqStack *s);操作结果:得到运算符栈的栈顶元素void Push(SqStack *s,char e);操作结果:对运算符栈进行压栈操作int IsNumber(char c);操作结果:判断一个字符是否是数字int MidExpression_Eval(char Express[]);操作结果:计算中缀表达式的值int Operate (int a,char x,int b);操作结果:计算表达式axb,并返回结果六、详细设计#include<iostream>#include<malloc.h>using namespace std;/*定义区*/#define STACK_INIT_SIZE 100#define STACKINCREMENT 10#define OVERFLOW -1#define ERROR 0#define OK 1//运算符栈typedef struct{char *base, *top;int stacksize;}SqStack;//运算数栈typedef struct{int *base, *top;int stacksize;}SqStack1;/*priority是用于比较符号优先级的全局二维数组*/int priority[7][7] = {{ '>', '>', '<', '<', '<', '>', '>' },{ '>', '>', '<', '<', '<', '>', '>' },{ '>', '>', '>', '>', '<', '>', '>' },{ '>', '>', '>', '>', '<', '>', '>' },{ '<', '<', '<', '<', '<', '=', ' ' },{ '>', '>', '>', '>', ' ', '>', '>' },{ '<', '<', '<', '<', '<', ' ', '=' }};void InitStack(SqStack &s)//初始化运算符栈{s.base = (char *)malloc(STACK_INIT_SIZE*sizeof(char));if (!s.base)exit(OVERFLOW); //若分配空间失败则退出s.top = s.base; //栈顶指针和栈底指针相同,表示空栈s.stacksize = STACK_INIT_SIZE; //栈的大小}void InitStack1(SqStack1 &s)//初始化运算数栈{s.base = (int *)malloc(STACK_INIT_SIZE*sizeof(int));if (!s.base)exit(OVERFLOW);s.top = s.base; //空栈s.stacksize = STACK_INIT_SIZE;//栈的大小}void PushS(SqStack &s, char e)//向运算符栈压入运算符{if (s.top - s.base >= s.stacksize)//栈满则realloc空间{s.base=(char *)realloc(s.base, (s.stacksize + STACKINCREMENT)*sizeof(char));if (!s.base)exit(OVERFLOW);s.top = s.base + s.stacksize;//指向新的栈顶s.stacksize += STACKINCREMENT; //空间加上stackincrement}*s.top++ = e;//压入运算符}void PushS1(SqStack1 &s, int e)//插入元素e为新的运算数的栈顶{if (s.top - s.base >= s.stacksize)//栈满则realloc空间{s.base = (int *)realloc(s.base, (s.stacksize + STACKINCREMENT)*sizeof(int));if (!s.base)exit(OVERFLOW);s.top = s.base + s.stacksize;//指向栈顶s.stacksize += STACKINCREMENT;}*s.top++ = e;//压入运算数}char GetTop(SqStack s)//若栈不空,则返回s的栈顶元素,否则返回ERROR{if (s.top == s.base) //栈为空return ERROR;return *(s.top - 1); //因为top指向栈顶元素的下一个位置}int GetTop1(SqStack1 s)//若栈不空,则用e返回s的栈顶元素,否则返回ERROR {if (s.top == s.base) //栈为空return ERROR;return *(s.top - 1); //因为top指向栈顶元素的下一个位置}int pop(SqStack &s, char &e)//若栈不空,则删除s的栈顶元素,用e返回其值{if (s.top == s.base)return ERROR;e = *--s.top; //先top指针下移,指向栈顶元素,再赋值给ereturn OK;}int pop1(SqStack1 &s, int &e)//若栈不空,则删除s的栈顶元素,用e返回其值{if (s.top == s.base)return ERROR;e = *--s.top; //先top指针下移,指向栈顶元素,再赋值给ereturn OK;}int number(char a)//运算符与数字的对应{switch (a){case '+': return 0; break;case '-': return 1; break;case '*': return 2; break;case '/': return 3; break;case '(': return 4; break;case ')': return 5; break;case '#': return 6; break;default : return ERROR;}}char precede(char a, char b)//两个运算先在priority数组中找到相应的优先顺序{int i, j;i = number(a);j = number(b);return priority[i][j];}int Operate(int a, char c, int b)//计算表达式结果并返回其值{switch (c) {case'+': return a + b;case'-': return a - b;case'*': return a * b;case'/': return a / b;default: return ERROR;}}int MidExpression_Eval(SqStack &s, SqStack1 &s1)//算术表达式求值,s为运算符栈,s1位运算数栈{//变量定义char c1, c2;char temp;int e, a, b;c1 = getchar();while (c1 != '#' || GetTop(s) != '#')//表达式未结束{if (c1 >= '0'&&c1 <= '9')//c1为数字{c2 = getchar();if(c2 != '#'&&c2 >= '0'&&c2 <= '9')//c2还是数字,这说明是一个多位数{e = ((int)c1 - 48) * 10 + (int)c2 - 48; //化为整型PushS1(s1, e); //压入操作数栈}//内层ifelse//c1为运算数,c2为运算符{PushS1(s1, (int)c1 - 48);//将运算数入栈again:if (c2 != '#' || GetTop(s) != '#') {switch (precede(GetTop(s), c2)) {case'<'://栈顶元素优先权低PushS(s, c2);break;case'='://脱括号并接收下一个字符pop(s, c2);break;case'>'://退栈并将运算结果入栈pop(s, temp);pop1(s1, b);pop1(s1, a);PushS1(s1, Operate(a, temp, b));goto again;}//switch}//ifelsegoto exit;//计算完成晚会结果}//内层else}//ifelse {aga:if (c1 != '#' || GetTop(s) != '#') {switch (precede(GetTop(s), c1)) {case'<'://栈顶元素优先权低PushS(s, c1);break;case'='://脱括号并接收下一个字符pop(s, c1);break;case'>'://退栈并将运算结果入栈pop(s, temp);pop1(s1, b);pop1(s1, a);PushS1(s1, Operate(a, temp, b));goto aga;} //switch}//ifelsegoto exit;//计算结束返回结果}c1 = getchar();}//whileexit:return GetTop1(s1);}int main() {SqStack optr;//运算符栈SqStack1 opnd;//运算数栈int result;InitStack(optr);//初始化运算符栈PushS(optr, '#');//‘#’为栈底元素,标志结束InitStack1(opnd);//初始化运算数栈cout <<"请输入表达式,'#'表示结束"<< endl;result = MidExpression_Eval(optr, opnd);cout <<"表达式的结果为"<< result << endl;return 0;}七、调试结果(运行结果)八、实验心得与总结1.注意到priority[4][6]和priority[6][5]处优先级为空(‘’),但是没错,这是因为运算符( 一定会被) 消去,不可能与# 比较优先级,同理# 也不会和) 比较优先级。