表达式求值算法

合集下载

计算逻辑表达式的值算法

计算逻辑表达式的值算法

计算逻辑表达式的值算法一、引言在计算机科学和数学领域,逻辑表达式是一个由逻辑运算符和逻辑变量组成的表达式,用于表示逻辑关系。

计算逻辑表达式的值是解析和计算这些逻辑运算符和变量的结果。

本文将介绍一种常见的算法,用于计算逻辑表达式的值。

二、逻辑运算符逻辑运算符是用于连接和操作逻辑表达式的符号。

常见的逻辑运算符包括与(AND)、或(OR)、非(NOT)以及它们的扩展形式。

1. 与(AND)运算符用于连接两个逻辑表达式,当且仅当两个表达式都为真时,结果才为真。

其符号通常表示为“&&”或“∧”。

2. 或(OR)运算符用于连接两个逻辑表达式,当至少有一个表达式为真时,结果为真。

其符号通常表示为“||”或“∨”。

3. 非(NOT)运算符用于对逻辑表达式进行取反操作,即如果表达式为真,则结果为假;如果表达式为假,则结果为真。

其符号通常表示为“!”或“¬”。

三、逻辑变量逻辑变量是用于表示逻辑状态的变量。

逻辑变量只能取两个值之一,真(True)或假(False)。

在计算逻辑表达式的值时,需要根据逻辑变量的取值来计算结果。

计算逻辑表达式的值算法可以通过递归或迭代的方式实现。

下面以递归算法为例,介绍计算逻辑表达式的值的步骤。

1. 输入逻辑表达式。

2. 如果表达式是一个逻辑变量,则返回该变量的取值。

3. 如果表达式是一个与(AND)运算符,则递归计算左右两个子表达式的值,然后根据运算规则计算结果。

4. 如果表达式是一个或(OR)运算符,则递归计算左右两个子表达式的值,然后根据运算规则计算结果。

5. 如果表达式是一个非(NOT)运算符,则递归计算子表达式的值,然后根据运算规则计算结果。

6. 返回计算结果。

五、示例假设有一个逻辑表达式:A && (B || C) && !D,其中A、B、C、D 分别代表逻辑变量。

1. 输入逻辑表达式。

2. 计算A的取值。

3. 计算B的取值。

c语言算术表达式求值

c语言算术表达式求值

c语言算术表达式求值【实用版】目录1.引言2.C 语言算术表达式的基本概念3.C 语言算术表达式的求值方法4.实际应用示例5.总结正文【引言】在 C 语言编程中,算术表达式是用来进行数值计算的重要工具。

本篇文章将为大家介绍 C 语言算术表达式的求值方法。

【C 语言算术表达式的基本概念】C 语言中的算术表达式主要包括以下几种:1.一元运算符:例如+、-、*、/等,用于对一个数值进行操作。

2.二元运算符:例如+、-、*、/等,用于对两个数值进行操作。

3.关系运算符:例如<、>、<=、>=、==、!=等,用于比较两个数值的大小或相等性。

4.逻辑运算符:例如&&、||、! 等,用于进行逻辑判断。

【C 语言算术表达式的求值方法】C 语言中,算术表达式的求值主要遵循以下规则:1.先进行括号内的运算,再进行括号外的运算。

2.先进行乘除法运算,再进行加减法运算。

3.关系运算符和逻辑运算符的优先级较低,从左到右依次进行运算。

【实际应用示例】下面我们通过一个实际的 C 语言程序,来演示算术表达式的求值过程。

```c#include <stdio.h>int main() {int a = 10, b = 5;int result;result = a + b * (a - b) / (a * b);printf("The result is: %d", result);return 0;}```在这个程序中,我们定义了两个整数变量 a 和 b,并通过算术表达式计算 result 的值。

根据我们之前提到的算术表达式求值规则,我们可以将这个表达式分解为以下几个步骤:1.计算括号内的值:a - b = 10 - 5 = 52.计算乘法运算:b * (a - b) = 5 * 5 = 253.计算除法运算:(a * b) / (a * b) = 14.计算加法运算:a + 25 = 10 + 25 = 355.输出结果:printf("The result is: %d", result); 输出 35【总结】通过本篇文章的介绍,相信大家已经对 C 语言算术表达式的求值方法有了更加深入的了解。

基于二叉树的表达式求值算法实验报告

基于二叉树的表达式求值算法实验报告

基于二叉树的表达式求值算法实验报告一、实验目的1. 学习基于二叉树的表达式求值算法。

2. 掌握二叉树的遍历方法和递归算法。

3. 设计并实现基于二叉树的表达式求值程序。

二、实验环境操作系统:Windows 10开发环境:Visual Studio Code 1.57.1编程语言:C++三、算法描述1. 表达式转二叉树将中缀表达式转换为二叉树的过程可以通过递归算法实现。

具体步骤如下:(1)如果表达式只有一个数字,那么将其作为叶子节点返回。

(2)如果表达式包含多个操作符,则以操作符优先级最低的操作符为根节点,将表达式分成两部分,分别递归处理左子树和右子树。

(3)如果表达式中有括号,则将括号中的表达式作为一棵子树递归处理。

2. 表达式求值二叉树求值的过程可以通过递归算法实现。

对于一个二叉树节点,分别计算其左子树和右子树的值,并根据节点的操作符计算节点的值。

具体步骤如下:(1)如果节点是叶子节点,则其值为对应数字。

(2)如果节点是加法节点,则将左右子树的值相加。

(3)如果节点是减法节点,则将左子树的值减去右子树的值。

(4)如果节点是乘法节点,则将左右子树的值相乘。

(5)如果节点是除法节点,则将左子树的值除以右子树的值。

四、实验步骤1. 定义二叉树节点结构体c++struct node {char oper; 节点的操作符double val; 节点的值node* left; 左子树节点node* right; 右子树节点};2. 实现表达式转二叉树函数c++node* expressionToTree(string exp) { int len = exp.length();node* root = NULL;如果表达式是一个数字if (len == 1) {root = new node;root->oper = '#';root->val = exp[0] - '0';root->left = NULL;root->right = NULL;return root;}如果表达式包含多个操作符int pos = 0, priority = 0;for (int i = 0; i < len; i++) {if (exp[i] == '(') {priority += 10;continue;}if (exp[i] == ')') {priority -= 10;continue;}if (exp[i] == '+' exp[i] == '-') {if (priority <= 1) {root = new node;root->oper = exp[i];root->left = expressionT oTree(exp.substr(pos, i - pos));root->right = expressionToTree(exp.substr(i + 1));return root;}}if (exp[i] == '*' exp[i] == '/') {if (priority <= 2) {root = new node;root->oper = exp[i];root->left = expressionT oTree(exp.substr(pos, i - pos));root->right = expressionToTree(exp.substr(i + 1));return root;}}}return root;}3. 实现表达式求值函数c++double evaluate(node* root) {if (root == NULL) return 0.0;if (root->left == NULL && root->right == NULL) return root->val;double left_val = evaluate(root->left), right_val =evaluate(root->right);switch (root->oper) {case '+': return left_val + right_val;case '-': return left_val - right_val;case '*': return left_val * right_val;case '/': return left_val / right_val;default: return 0.0;}}4. 测试程序c++int main() {string exp = "((5-2)*(3+4))/7";node* root = expressionToTree(exp);cout << exp << " = " << evaluate(root) << endl; 输出结果为3 return 0;}五、实验结果分析本实验设计并实现了基于二叉树的表达式求值程序。

表达式求值算法总结(C++)

表达式求值算法总结(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++四则运算表达式求值算法
的字符串。
u 这里定义了两个构造函数,不带参数的默认 m_string 为空,带 string 类型
参数的将参数值赋予成员变量 m_string,此外还定义了赋值运算符“=”,
目 的是将一个表达式字符串 赋予 成员变量 m_string 。 因此 生 成一个 ExpressionType 的对象可以有如下两种形式: ExpressionType expr(“(2.99-4.32)*(90.8-78.66)+78.0/3.14”); 或者 ExpressionType expr; Expr = “(2.99-4.32)*(90.8-78.66)+78.0/3.14”; u DivideExpressionToItem(): 私有成员函数,返回值是一个 string 类型的 队列。其功能是将原始的中缀表达式中的操作数、操作符以及括号按顺序以 字符串的形式分解出来,然后保存在一个队列中(队列的操作规则是先进先 出)。 u ChangeToSuffix(): 私有成员函数,返回值是一个 string 类型的栈。其功 能是将队列中表示原始表达式各项的字符串调整顺序,转换成后缀表达式的 顺序,并处理掉括号,然后保存在一个栈中(栈的操作规则是先进后出)。 u IsWellForm():私有成员函数,返回 bool 值。其功能是判断原始表达式中的 括号是否匹配,如果匹配返回 true,否则返回 false。 u Size():返回原始表达式所包含的字节数。 u Calculate(): 公有成员函数,返回 double 类型的值。其功能是计算转换后 的后缀表达式的值,即原始中缀表达式的值。
abc然后分别按从左到右放入栈中如果碰到操作符就从栈中弹出两个操作数进行运算最后再将运算结果放入栈中依次进行直到表达式放入栈中然后碰到操作符则从栈中弹出的运算并将其结果d假设为放入栈中最后是操作符所以再弹出进行dc运算并将其结果再次放入栈中此时表达式结束则栈中的元素值就是该表达式最后的运算结果

字符串表达式求值(支持多种类型运算符)

字符串表达式求值(支持多种类型运算符)

字符串表达式求值(⽀持多种类型运算符)⼀、说明1. 输⼊字符串为中缀表达式,⽆需转为后缀表达式2. ⽀持的运算符包括:算术运算符:"+,-,*,/"关系运算符:">,<,>=,<=,=,!="(注意等于运算符采⽤的是⼀个等号)逻辑运算符:"&&,||"3. ⽀持⼤于10的数字,不⽀持负数操作数,但⽀持中间结果和返回值为负数⼆、算法原理&步骤本⽂算法对中缀表达式形式字符串进⾏求值,同时⽀持与或运算和逻辑运算(若含有关系运算符或者逻辑运算符,则输出为1或者0)。

类似于加减乘除,将关系运算符和逻辑运算符看作优先级低的运算符进⾏处理,优先级:算术运算符>关系运算符>逻辑运算符。

步骤:1. 初始化两个空堆栈,⼀个存放操作数,⼀个存放运算符。

2. 从左⾄右扫描输⼊字符串,依次读取。

2.1 若为操作数,则压⼊操作数栈;2.2 若为运算符,判断其优先级是否⼤于运算符栈栈顶元素优先级。

若⼤于栈顶元素优先级,则直接压栈;否则,弹出栈顶元素operator,同时依次从操作数栈中弹出两个元素number1,number2,计算表达式(number2 operator number1)的值value,并将值value压⼊操作数栈。

重复上述过程直⾄当前扫描的操作符优先级⼤于栈顶元素,然后将当前运算符压栈。

3. 弹出运算符栈顶元素operator,同时依次从操作数栈中弹出两个元素number1,number2,计算表达式(number2 operator number1)的值value,并将值value压⼊操作数栈。

重复上述过程直⾄运算符栈为空。

4. 此时操作数栈应该只有⼀个元素,即为表达式的值。

三、代码&测试求值函数:1/* 字符串表达式求值2 * @param input: 输⼊的字符串3 * @param output: 表达式的值,若含有关系运算符则为1或者04 * return 计算过程是否正常5*/6bool ExpValue(string input,int& output)7 {8 stack<int> operand_stack;9 stack<string> operator_stack;1011char prev = 0; // 上⼀个属于运算符的字符12for (int i = 0; i < input.size(); i++)13 {14char c = input[i];15// prev是否是⼀个完整运算符16if (!isOperator(c) && prev)17 {18string new_op = string("").append(1, prev);19 addNewOperator(new_op, operand_stack, operator_stack);20 prev = 0;21 }2223// 数字24if (isdigit(c))25 {26int val_c = c - '0';27if (i > 0 && isdigit(input[i - 1]))28 {29int top_num = operand_stack.top();30 top_num = top_num * 10 + val_c;31 operand_stack.pop();32 operand_stack.push(top_num);33 }34else35 operand_stack.push(val_c);36 }37// 运算符字符38else if (isOperator(c))39 {40// 处理两字符运算符41if (prev)42 {43string new_op = string("").append(1, prev).append(1, c);44 addNewOperator(new_op, operand_stack, operator_stack);45 prev = 0;46 }47else48 prev = c;49 }50else if (c == '(')51 operator_stack.push("(");52else if (c == ')')53 {54// 处理括号内的运算符55while (operator_stack.top()!="(")56 {57int num1 = operand_stack.top();58 operand_stack.pop();59int num2 = operand_stack.top();60 operand_stack.pop();61string op = operator_stack.top();62 operator_stack.pop();6364int val = Calculate(num2, num1, op);65 operand_stack.push(val);66 }67 operator_stack.pop(); // 弹出"("68 }69 }70 assert(operand_stack.size() == operator_stack.size() + 1);71// 弹出所有运算符72while(!operator_stack.empty())73 {74int num2 = operand_stack.top();75 operand_stack.pop();76int num1 = operand_stack.top();77 operand_stack.pop();78string op = operator_stack.top();79 operator_stack.pop();8081int val = Calculate(num1, num2, op);82 operand_stack.push(val);83 }8485if (operand_stack.size() == 1) {86 output = operand_stack.top();87return true;88 }89return false;90 }其中⽤到的⼦函数有:/* 判断字符是否属于运算符 */bool isOperator(char c){switch (c){case'-':case'+':case'*':case'/':case'%':case'<':case'>':case'=':case'!':case'&':case'|':return true;default:return false;}}/* 获取运算符优先级 */int getPriority(string op){int temp = 0;if (op == "*" || op == "/" || op == "%")temp = 4;else if (op == "+" || op == "-")temp = 3;else if (op == ">" || op == "<" || op == ">=" || op == "<="|| op == "=" || op == "!=")temp = 2;else if (op == "&&" || op == "||")temp = 1;return temp;}/** 返回⼀个两元中缀表达式的值* syntax: num_front op num_back* @param num_front: 前操作数* @param num_back: 后操作数* @param op: 运算符*/int Calculate(int num_front, int num_back, string op){if (op == "+")return num_front + num_back;else if (op == "-")return num_front - num_back;else if (op == "*")return num_front * num_back;else if (op == "/")return num_front / num_back;else if (op == "%")return num_front % num_back;else if (op == "!=")return num_front != num_back;else if (op == ">=")return num_front >= num_back;else if (op == "<=")return num_front <= num_back;else if (op == "=")return num_front == num_back;else if (op == ">")return num_front > num_back;else if (op == "<")return num_front < num_back;else if (op == "&&")return num_front && num_back;else if (op == "||")return num_front || num_back;return0;}/* 新运算符⼊栈操作 */void addNewOperator(string new_op, stack<int>& operand_stack, stack<string>& operator_stack) {while (!operator_stack.empty() && getPriority(operator_stack.top()) >= getPriority(new_op)){int num2 = operand_stack.top();operand_stack.pop();int num1 = operand_stack.top();operand_stack.pop();string op = operator_stack.top();operator_stack.pop();int val = Calculate(num1, num2, op); operand_stack.push(val);}operator_stack.push(new_op);}View Code测试结果:int main(){string s0 = "10-1*10+3%2";string s1 = "100 + (3-33)*2";string s2 = "20+1 >= 20 && 20+1 < 20"; string s3 = "10>20 || 10/1>=5";int ret = -1;if (ExpValue(s0, ret))cout << s0 << "的值: " << ret << endl; if (ExpValue(s1, ret))cout << s1 << "的值: " << ret << endl; if (ExpValue(s2, ret))cout << s2 << "的值: " << ret << endl; if (ExpValue(s3, ret))cout << s3 << "的值: " << ret << endl; return0;}上述代码的执⾏结果为:。

数据结构 3.5表达式求值

数据结构 3.5表达式求值
}}
1) 设立暂存运算符的栈; 2) 设表达式的结束符为“#”, 予设运算符栈的栈
底为“#” 3) 若当前字符是操作数, 则直接发送给后缀式; 4) 若当前运算符的优先数高于栈顶运算符,则进
栈;若当前运算符是左圆括号,则进栈;
5) 若当前运算符是右圆括号, 退出栈顶运算符发 送给后缀式,直至退出的栈顶运算符是左圆括 号为止; 若当前运算符优先数小于等于栈顶运 算符,则退出栈顶运算符发送给后缀式
例如: Exp = a b + (c d / e) f
前缀式: 中缀式: 后缀式:
+abc/def ab+cd/ef abcde/f+
结论
1)操作数之间的相对次序不变 2)运算符的相对次序不同 3)中缀式丢失了括弧信息,致使运算的次序不
确定; 4)前缀式的运算规则为:连续出现的两个操作数和
{ WRT(n-1); printf("%d", n);} }
例2、指出下列程序段的功能是什么? (1) void demo1(seqstack *s){
int i;arr[64];n=0; while (!stackempty(s))
arr[n++]=pop(s); for(i=0;i<n;i++) push(s,arr[i]); }
(2) void demo2(seqstack *s,int m){ seqstack t; int i; initstack(t); while(! Stackempty(s)) if(i=pop(s)!=m) push(t,i);
While(! Stackempty(t)) { i=pop(t); push(s,i);

利用栈来实现算术表达式求值的算法

利用栈来实现算术表达式求值的算法

利用栈来实现算术表达式求值的算法利用栈来实现算术表达式求值的算法算术表达式是指按照一定规则组成的运算式,包含数字、运算符和括号。

在计算机中,求解算术表达式是一项基本的数学运算任务。

根据算术表达式的性质,我们可以考虑利用栈这一数据结构来实现求值算法。

一、算法思路首先,我们需要明确一个重要概念——逆波兰表达式(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))```四、总结算术表达式求值是一项常见的数学运算任务,利用栈这一数据结构来实现求值算法是一种简单有效的方法,它将中缀表达式转化为逆波兰表达式后,可以消除括号并减少运算符的优先级关系,从而提高程序的执行效率。

逆波兰表达式求值算法

逆波兰表达式求值算法

逆波兰表达式求值算法逆波兰表示法(Reverse Polish Notation,RPN)是一种数学表达式表示法,它不需要括号来明确操作符的优先级。

在这种表示法中,操作符跟在操作数后面。

下面是一个逆波兰表达式的求值算法:1. 初始化一个堆栈用于存储数字。

2. 从左到右读取表达式中的每个字符。

3. 如果字符是一个数字,则将其转换为对应的数值,并压入堆栈。

4. 如果字符是一个操作符(例如加号、减号、乘号或除号),则从堆栈中弹出两个操作数,进行相应的运算,并将结果压回堆栈。

5. 重复步骤2-4,直到表达式结束。

6. 最后,堆栈中剩下的唯一元素就是表达式的计算结果。

下面是一个使用 Python 实现逆波兰表达式求值算法的示例代码:```pythondef eval_rpn(expression):stack = []operators = set('+-/')for token in ():if token not in operators:(int(token))else:y = ()x = ()if token == '+':(x + y)elif token == '-':(x - y)elif token == '':(x y)else: token == '/'(x // y) 使用整数除法,因为逆波兰表达式通常用于整数运算 return stack[0]```使用示例:```pythonexpression = "2 3 + 4 " 计算 (2 + 3) 4 的结果,即 20 result = eval_rpn(expression)print(result) 输出:20```。

表达式求值(数据结构)

表达式求值(数据结构)
ch (3) 当ch != “#” 时, 执行以下工作, 否则
结束算法,此时在OPND栈的栈顶得到 运算结果。
① 若ch是操作数,进OPND栈,从中缀表达式 取下一字符送入ch; ② 若ch是操作符,比较栈外icp(ch)的优先级和 栈内isp(OPTR)的优先级: 若icp(ch) > isp(OPTR),则ch进OPTR栈, 从中缀表达式取下一字符送入ch; 若icp(ch) < isp(OPTR),则从OPND栈退出 a2 和 a1 , 从 OPTR 栈 退 出 θ, 形 成 运 算 指 令 (a1)θ(a2),结果进OPND栈; 若icp(ch) == isp(OPTR) 且ch == “)”,则从 OPTR栈退出栈顶的“(”,对消括号,然后从 中缀表达式取下一字符送入ch;
优先级 操作符
1
单目-、!
2
*、/、%
3
+、-
4 <、<=、>、>=
5
==、!=
6
&&
7
||
一般表达式的操作符有4种类型:
1 算术操作符 如双目操作符(+、-、 *、/ 和%)以及单目操作符(-);
2 关系操作符 包括<、<=、==、!=、 >=、>。这些操作符主要用于比较;
3 逻辑操作符 如与(&&)、或(||)、非 (!);
38
icp (栈外) 0 8 6 4
21
isp叫做栈内(in stack priority)优先数。
icp叫做栈外(in coming priority)优先数。
操作符优先数相等的情况只出现在括号 配对或栈底的“;”号与输入流最后的“;” 号配对时。

表达式求值算法

表达式求值算法

表达式求值算法表达式求值算法是计算机科学中的重要概念之一,用于计算数学表达式的结果。

在编程语言中,表达式求值是一项基本的操作,并且经常在计算过程中需要用到。

本文将介绍一些常见的表达式求值算法及其实现。

1. 逆波兰表达式法逆波兰表达式法是一种用于计算数学表达式的算法,它使用后缀表达式(也称为逆波兰表达式)来表示表达式。

逆波兰表达式是将操作符放在操作数之后的一种表示方法。

对于任意一个数学表达式,都可以通过将中缀表达式转换为后缀表达式,然后使用栈结构计算得到结果。

逆波兰表达式法的优点是计算顺序明确,不需要考虑运算符的优先级和括号的处理。

2. 中缀表达式转后缀表达式法中缀表达式是我们常见的数学表达式,如 3 + 4 * 5。

在中缀表达式中,操作符的优先级和括号起着很大的作用。

为了将中缀表达式转换为后缀表达式,我们需要使用到栈结构。

具体的算法如下:- 遍历中缀表达式的每个元素。

- 如果是操作数,则直接输出。

- 如果是操作符,则判断其与栈顶操作符的优先级,决定是否将其压入栈。

- 如果是左括号,则直接压入栈。

- 如果是右括号,则依次弹出栈顶操作符,并输出,直到遇到左括号为止。

- 遍历完表达式后,如果栈不为空,则依次弹出栈顶操作符,并输出。

3. 后缀表达式求值法后缀表达式(逆波兰表达式)的求值方法相对简单。

我们可以使用栈结构来计算后缀表达式的结果。

具体的算法如下:- 遍历后缀表达式的每个元素。

- 如果是操作数,则将其压入栈。

- 如果是操作符,则弹出栈顶的两个操作数,执行相应的计算,并将结果压入栈。

- 遍历完后缀表达式后,栈中最后剩下的元素即为计算结果。

4. 二叉树表示法除了逆波兰表达式法和中缀表达式法,我们还可以使用二叉树来表示表达式,并通过遍历二叉树来计算表达式的结果。

具体的算法如下:- 构建二叉树,将表达式的操作符作为根节点,将操作数作为叶节点。

- 通过后序遍历二叉树,计算出每个子树的值,并将结果返回给其父节点。

表达式求值及符号推导

表达式求值及符号推导

表达式求值及符号推导
本文将围绕表达式的求值及符号推导展开,首先介绍一下表达式求值,表达式求值是一种
数学算法,它通过对一组变量、符号及常量的组合,来求得最终的结果。

表达式可以包含
操作符,如 + 和-,也可以是数学函数,如 sin、cos、tan 和 log。

表达式求值的常见
方法有两种:使用栈的方法或者使用递归的方法。

符号推导就是将状态变量、操作符等符号形式的表达式转化为一个或多个简洁、正确的算
法表达式形式,这就需要我们根据表达式当中的符号、变量等内容进行分析,把表达式转
换为算数表达式供程序进行求值。

这里有两种最基本的推导方法,一是预处理符号表达式,即使用一定规则将表达式转换为更简单的求值格式,这里提到的简化是指转换表达式的方法,而不是算术求值的方法;二是函数代换,函数推导过程通过从表达式当中选出终结符,将它们替换为原子函数,从而得到计算函数。

综上所述,表达式求值是对变量、常量及操作符的一种计算方法,可以使用栈或递归算法
进行,而符号推导则是将不同符号的表达式转换为便于程序计算的算数表达式,多是采用
预处理符号表达式或函数代换的方法,需要我们通过分析推导出适当的算法表达式。

c语言基于二叉树的表达式求值算法

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,得到最终结果。

表达式求值算法

表达式求值算法

表达式求值算法表达式求值是一种将数学表达式转换为计算结果的算法。

在计算机程序中,表达式是由操作符和操作数组成的,操作符是执行特定计算操作的符号,操作数是参与计算的数值。

在表达式求值算法中,我们需要处理不同类型的表达式,例如算术表达式、逻辑表达式和位运算表达式等。

算术表达式包含加法、减法、乘法、除法等操作符,逻辑表达式包含与、或、非等操作符,位运算表达式包含位与、位或、位取反等操作符。

实现一个通用的表达式求值算法需要将所有这些操作符纳入考虑,并按照特定的规则进行计算。

在表达式求值算法中,首先需要对表达式进行解析,将其拆分为操作符和操作数。

通过使用逆波兰表达式或分析树等数据结构,我们可以更方便地对表达式进行计算。

逆波兰表达式是一种将操作符放在操作数后面的表达式表示方法。

例如,中缀表达式"3 + 4 * 2"可以转换为逆波兰表达式"3 4 2 * +"。

逆波兰表达式的好处是可以通过一个栈来进行计算。

遍历逆波兰表达式的每个元素,当遇到操作数时,将其压入栈中;当遇到操作符时,从栈中弹出相应数量的操作数进行计算,并将结果压入栈中。

最后,栈中剩下的唯一一个元素就是表达式的结果。

另一种求值算法是使用分析树。

分析树是一种用树结构表示表达式的方法,树的每个节点都是一个操作符,而叶子节点是操作数。

通过遍历分析树,从叶子节点开始计算,并将结果返回给父节点,直到整个树的根节点成为最终结果。

这种方法可以递归地处理任意复杂的表达式。

除了使用逆波兰表达式和分析树,我们还可以使用其他方法来实现表达式求值算法。

例如,我们可以使用栈来存储操作数,并在遍历表达式时进行计算。

当遇到操作符时,从栈中弹出相应数量的操作数进行计算,并将结果压入栈中。

在表达式求值算法中,需要注意处理运算符的优先级和结合性。

不同的运算符可能有不同的优先级,例如乘法和除法的优先级高于加法和减法。

结合性指的是同一级别的运算符如何进行计算,例如加法和减法是左结合的,而赋值运算符是右结合的。

表达式求值算法

表达式求值算法

1. 中缀表达式转换成后缀表达式将中缀表达式转化为后缀表达式时,遇到运算对象时直接放后缀表达式中,假设中缀表达式本身合法且在字符串InExp中,转换后的后缀表达式存储在字符串PostExp中。

具体做法:遇到运算对象时存储在后缀表达式字符串PostExp中,遇到运算符时类似于中缀表达式求值时对运算符的处理过程,但运算符出栈后不是进行相应的运算,而是将其送入后缀表达式字符串PostExp中存放。

算法的程序实现如下:void ExpInToPost(char *InExp,char *PostExp){ /* 算术表达式从中缀形式转换为后缀形式算法。

设OPTR为运算符栈,OpSet为运算符集合。

*/LinkStack OPTR;char ch,op;InitStack (OPTR);Push (OPTR, '#');ch=*InExp++;GetTop(OPTR,op);while (ch!= '#' || op!= '#'){if (!In(ch, OpSet)) // 不是运算符则进栈{*PostExp++=ch;ch=*InExp++;}else{GetTop(OPTR,op);switch (precede(op, ch) )//与栈顶运算符优先级比较{case '<': // 栈顶元素优先级低Push(OPTR, ch); ch=*InExp++;break;case '=': // 优先级相等Pop(OPTR, ch); ch=*InExp++;break;case '>':// 栈顶元素优先级高Pop(OPTR, op); *PostExp++=op;break;} // switchGetTop(OPTR,op);}} // whileif(!IsStackEmpty(OPTR)) //栈不空,出栈加到后缀表达式字符串尾{Pop(OPTR, op);*PostExp++=op;}*PostExp='\0'; //加字符串结束标志} // ExpInToPost2. 后缀表达式求值具体做法:只使用一个对象栈,当从左向右扫描表达式时,每遇到一个操作数就送入栈中保存,每遇到一个运算符就从栈中取出两个操作数进行当前的计算,然后把结果再入栈,直到整个表达式结束,这时送入栈顶的值就是结果。

用两种方法实现表达式自动计算

用两种方法实现表达式自动计算

一、设计思想计算算数表达式并求值,可以采取两种算法:1.先将算术表达式转化为后缀表达式,然后对后缀表达式进行计算。

2.直接对算术表达式进行计算。

下面依次对两种方法进行分析:第一种算法有两步1.先将算数表达式转化为后缀表达式。

在计算过程中,第一,要先建立一个存放操作符的栈和一个存放数字的数组。

首先对用户输入的表达式进行扫面,如果是数字或者是小数点,直接存入数组。

如果是操作符,就判断是否为空或者是否为“(”或者是否它的优先级大于操作符栈顶的优先级,如果是,就入栈,索引后移;如果它的优先级不大于栈顶操作符,栈顶的操作符出栈,进入数组,如此循环,直到栈顶的优先级小于扫描到的操作符的优先级的时候,操作符入栈,索引后移。

当遇到标识符\0时,扫描结束。

数组中存放的就是后缀表达式。

2.利用后缀表达式进行计算。

得到后缀表达式后,要计算就需要用到数值栈。

首先对后缀表达式进行扫描,遇到数字字符,将数字字符转化为浮点类型,放入数值栈中,遇到操作符,就从数值栈中取出两个数,进行计算后将计算结果再放入数值栈中,扫描下一个,最后的计算结果就存到了数值栈中,直接取出数值栈栈顶元素,就是计算的最后结果。

第二种算法首先要建立两个栈,一个存放操作符的栈,一个是存放数值的栈。

然后开始对用户输入的表达式进行扫描,如果是数值或是小数点,就将其转化为浮点型数据,然后进入数值栈;如果是操作符,当前索引下的操作符的优先级如果不大于栈顶操作符的优先级,就将栈顶操作符取出来,从数值栈中取出两个数值,进行计算,结果存入数值栈。

如此循环,直到栈顶操作符的优先级小于当前索引的操作符的优先级是,操作符入栈,然后对下一个字进行扫描。

如果是左括号,则不进行优先级的比较,直接入栈。

如果是右括号,则从数值栈中取两个操作数,符号栈中取出一个符号,然后进行计算后得数放入数栈中,不断进行此类操作,直到从栈中取出的是左括号为止,左括号丢弃,扫描下一个。

扫描结束后,数值栈中存放的数值就是计算产生的结果,最后把数值从数值栈中取出,就是所得的计算结果。

基于二叉树的表达式求值算法

基于二叉树的表达式求值算法

基于二叉树的表达式求值算法二叉树的表达式求值算法可以使用递归来实现,具体步骤如下:1. 若该节点为数字节点,则直接返回节点的值;2. 若该节点为操作符节点,则递归计算其左右子树的值,并根据操作符进行计算,最终返回计算结果。

所以,我们可以先构建一个二叉树,然后对二叉树进行递归遍历,实现表达式的求值。

具体实现如下:pythonclass TreeNode:def __init__(self, val):self.val = valself.left = Noneself.right = Nonedef evaluate(root: TreeNode) -> int:"""对二叉树进行递归遍历,实现表达式的求值"""# 如果当前节点为数字,直接返回节点的值if not root.left and not root.right:return int(root.val)# 递归计算左子树的值和右子树的值left_val = evaluate(root.left)right_val = evaluate(root.right)# 根据运算符计算当前节点的值if root.val == '+':return left_val + right_valelif root.val == '-':return left_val - right_valelif root.val == '*':return left_val * right_valelse:return left_val right_val这里假设输入的二叉树是合法的,即括号、运算符和操作数的顺序都正确,不需要进行错误处理。

算术表达式求值算法解析

算术表达式求值算法解析
迭代算法
迭代算法在处理复杂表达式时效率较高,因为避免了重复计算,但在处理简单表达式时,由于需要遍历整个表达 式,效率较低。
算法适用范围比较
递归算法
递归算法适用于处理简单的算术表达式 ,如加减乘除等。
VS
迭代算法
迭代算法适用于处理复杂的算术表达式, 如包含括号、指数、对数等运算的表达式 。
算法优缺点比较
预测分析法的优点是处理效率较高,适用于大规模的算术 表达式处理,但缺点是需要使用大量的栈空间,且对于复 杂的算术表达式处理能力有限。
逆波兰表示法
逆波兰表示法是一种不需要括号来表示运算符优先级的方法,通 过将操作数放在前面,运算符放在后面来表示算术表达式。
逆波兰表示法将算术表达式转换为逆波兰表示形式后,可以直接 从左到右依次读取并计算表达式的值。
高程序的执行效率。例如,通过消除冗余计算、简化表达式等手段来优
化代码。
在数学计算器中的应用
表达式求值
数学计算器需要能够对用户输入的算术表达式进行求值,以便得到计算结果。算术表达式求值算法可以用于实现这一 功能,快速准确地计算表达式的值。
符号计算
数学计算器可能需要支持符号计算,即对包含未知数的算术表达式进行求解。算术表达式求值算法可以用于实现符号 计算,通过迭代和近似方法求解表达式的根或极值等。
多精度计算
在一些情况下,数学计算器需要支持多精度计算,以避免浮点数精度问题。算术表达式求值算法可以用 于实现多精度计算,提供更高的计算精度和可靠性。
在人工智能领域的应用
机器学习
数据推理
在机器学习领域,算术表达式求值算 法可以用于实现特征工程和模型训练 过程中的数值计算。例如,在神经网 络训练中,需要对权重、偏差等参数 进行迭代更新,算术表达式求值算法 可以高效地完成这些计算任务。

先序遍历表达式求值

先序遍历表达式求值

先序遍历表达式求值
摘要:
1.先序遍历表达式的概念
2.先序遍历表达式的求值方法
3.先序遍历表达式的应用实例
正文:
先序遍历表达式求值是计算机科学中的一种算法,主要用于计算二叉树中表达式的值。

先序遍历是指按照“根- 左-右”的顺序遍历二叉树。

在遍历过程中,我们可以通过对表达式中各个部分的求值,最终得到整个表达式的值。

求值方法如下:
1.首先,我们需要遍历二叉树的根节点,并将其值存储在一个变量中。

2.接下来,我们需要遍历左子树,并将遍历到的值与根节点的值进行运算(如加法、减法等),将结果存储在另一个变量中。

3.然后,我们需要遍历右子树,并将遍历到的值与上一步的结果进行运算,得到最终的表达式值。

在实际应用中,先序遍历表达式求值常用于计算二叉树中复杂表达式的值。

例如,给定一个二叉树,其根节点的值为5,左子树的值为3,右子树的值为2,我们可以通过先序遍历表达式求值得到该二叉树表示的表达式值为(5+3)*2=16。

总之,先序遍历表达式求值是一种有效的计算二叉树中复杂表达式值的方法。

通过按照“根- 左-右”的顺序遍历二叉树,并对表达式中各个部分进行
求值和运算,我们可以得到整个表达式的值。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、设计思想1.中缀表达式转换为前缀表达式。

首先创建算术符栈OPTR和表达式栈RESULT并置空,然后依次逆序检查中缀表达式每个字符,不同字符按不同情况处理:(1).若是空格直接跳过。

(2).若是操作数直接压入RESULT栈。

(3).若是‘)’直接存入OPTR栈,等待和它匹配的‘(’出现。

(4).若是‘(’表明括号中的终追表达式已转换完毕,则循环弹出OPTR栈的操作符,并压入RESULT栈,直到取出一个和它匹配的‘)’为止,‘)’出栈丢弃。

(5).若是运算符,如果OPTR栈是空的或者该运算符优先级高于或等于OPTR栈的栈顶运算符则入栈,如果该运算符优先级低,则循环弹出OPTR栈的运算符并存入RESULT,直到遇到栈顶的运算符优先级等于或小于该算法或栈空为止,然后将当前操作符存入OPTR栈。

若表达式扫描完后OPTR栈还有运算符,则依次弹出压入RESULT栈,直至栈空。

最后RESULT栈中的元素依次出栈存入字符串中,并向字符串中写入‘\0’,则字符串中存放的就是前缀表达式。

2.前缀表达式求值。

首先建立一个栈并置空,然后从右到左扫描前缀表达式,从右边第一个字符开始判断,如果当前字符是数字则一直到数字串的末尾再将整个数字串作为一个整体压人栈,如果是运算符,则将栈顶和次栈顶的两个“数字串”出栈并作相应的运算,然后将计算结果入栈。

扫描完前缀式后,栈中剩余的最后一个值就是前缀表达式的值。

3.中缀表达式转换成后缀表达式。

首先创建栈并置空,然后依次检查中缀表达式每个字符,不同字符按不同情况处理:(1).若是操作数,就直接将存入字符串exp[]中。

(2).若是‘(’则将其压入栈中。

(3).若是‘)’则依次弹栈并存入字符串exp[]中,直到遇到取出和它匹配的‘(’为止,‘(’出栈丢弃。

(4).若是操作符,如果栈空或者该操作符的优先级大于栈顶操作符则将其放入到栈中。

如果该操作符的优先级小于等于栈顶操作符则弹出栈中的操作符存入字符串exp[]中,直到该操作符的优先级大于栈顶操作符或栈空,然后将该操作符入栈。

当读到了中缀式的末尾时,如果栈非空则将栈中所有元素依次弹出存入字符串exp[]中,最后见‘\0’存入exp[]中,则exp[]中存储的就是后缀表达式。

4.后缀表达式求值。

首先建立一个栈并置空,然后依次左扫描后缀表达式,从第一个字符开始判断,如果当前字符是数字则一直到数字串的末尾再将整个数字串作为一个整体压人栈,如果是运算符,则将栈顶和次栈顶的两个“数字串”出栈并作相应的运算,然后将计算结果入栈。

扫描完前缀式后,栈中剩余的最后一个值就是前缀表达式的值。

二、算法流程图图1中缀式转前缀式流程图图2前缀式求值流程图图3中缀式转后缀式流程图图4后缀式求值流程图三、源代码下面给出的是算法实现的程序的源代码:#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 PrefixExpress(char str[],char exp[]);//将中缀表达式转化为前缀表达式float ComputePExpress(char a[]);//计算前缀式的值void SuffixExpress(char str[],char exp[]);//将中缀表达式转化为后缀表达式float ComputeSExpress(char s[]);//计算后缀表达式的值int pre(char c);//判断逆输入时的优先级int pre_1(char c);//判断优先级void main(){char a[MaxSize],b[MaxSize],c[MaxSize];float f,g;printf("请输入一个合法的算术表达式:\n");gets(a);printf("中缀表达式为:%s\n",a);PrefixExpress(a,c);printf("前缀表达式为:%s\n",c);g=ComputePExpress(c);printf("计算结果:%f\n",g);SuffixExpress(a,b);printf("后缀表达式为:%s\n",b);f=ComputeSExpress(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;}}int pre(char c)//判断优先级{int i;switch(c){case'(':i=3;break;case'+':i=1;break;case'-':i=1;break;case'*':i=2;break;case'/':i=2;break;case')':i=0;break;}return i;}int pre_1(char c)//判断优先级{int i;switch(c){case'(':i=0;break;case'+':i=1;break;case'-':i=1;break;case'*':i=2;break;case'/':i=2;break;case')':i=3;break;}return i;}void PrefixExpress(char str[],char exp[])//把中缀表达式转换为前缀表达式{SeqStack OPTR;SeqStack RESULT;int i,j=0;char ch;char e;i=strlen(str)-1;ch=str[i];InitStack(&OPTR);InitStack(&RESULT);while(i>=0)//依次逆扫描中缀式{switch(ch){case' ':break;case'\t':break;case')':PushStack(&OPTR,ch);break;case'(':PopStack(&OPTR,&e);while(e!=')'){PushStack(&RESULT,e);PopStack(&OPTR,&e);}break;case'+':case'-':case'*':case'/':if (StackEmpty(OPTR))PushStack(&OPTR,ch);else{GetTop(OPTR,&e);if(pre(ch)>=pre(e))PushStack(&OPTR,ch);else{while(pre(ch)<pre(e)&&!StackEmpty(OPTR)){PopStack(&OPTR,&e);PushStack(&RESULT,e);}PushStack(&OPTR,ch);}}break;default:while(ch>='0'&&ch<='9'){PushStack(&RESULT,ch);--i;ch=str[i];}PushStack(&RESULT,' ');++i;}--i;ch=str[i];}while(!StackEmpty(OPTR ))//将栈中剩余运算符出栈{PopStack(&OPTR,&e);PushStack(&RESULT,e);}while(!StackEmpty(RESULT))//依次出栈{PopStack(&RESULT,&e);exp[j] = e;++j;}exp[j]='\0';}float ComputePExpress(char a[])//计算前缀式的值{OpStack S;SeqStack A;int i;char e;float x1,x2,value;float result;i=strlen(a)-1;S.top=-1;InitStack(&A);while(i>=0){if(a[i]!=' '&&a[i]>='0'&&a[i]<='9'){while(a[i]!=' '){PushStack(&A,a[i]);i--;}value=0;while(!StackEmpty(A)){PopStack(&A,&e);value=value*10+e-'0';}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=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=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=x1/x2;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;}void SuffixExpress(char str[],char exp[])//把中缀表达式转换为后缀表达式{SeqStack S;char ch;char e;int i=0,j=0;InitStack(&S);ch=str[i];while(ch!='\0') //依次扫描中缀表达式{switch(ch){case'(':PushStack(&S,ch);break;case')':PopStack(&S,&e);while(e!='('){exp[j]=e;++j;PopStack(&S,&e);}break;case'+':case'-':case'*':case'/':if(StackEmpty(S))PushStack(&S,ch);else{GetTop(S,&e);if(pre_1(ch)>pre_1(e))PushStack(&S,ch);else{while(pre_1(ch)<=pre_1(e)&&!StackEmpty(S)){PopStack(&S,&e);exp[j]=e;++j;}PushStack(&S,ch);}}break;case' ':break;default:while(ch>='0'&&ch<='9'){exp[j]=ch;j++;++i;ch=str[i];}i--;exp[j]=' ';j++;}i++;ch=str[i];}while(!StackEmpty(S)) //将栈中剩余运算符出栈{PopStack(&S,&e);exp[j]=e;j++;}exp[j]='\0';}float ComputeSExpress(char a[])//计算后缀表达式的值{OpStack S;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;}四、运行结果图5 程序运行结果图五、遇到的问题及解决这部分我主要遇到了如下三个问题,其内容与解决方法如下所列:●问题1描述打印前缀表达式和后缀表达容易使不同乘数混淆不易于阅读。

相关文档
最新文档