表达式求值

合集下载

表达式求值问题课程设计

表达式求值问题课程设计

表达式求值问题课程设计一、课程目标知识目标:1. 学生能理解并掌握表达式求值的基本概念和规则,包括运算符优先级、括号的运用等。

2. 学生能够正确构建并简化数学表达式,熟练运用算术运算规则进行求值。

3. 学生能运用所学知识解决实际问题,如根据给定的条件编写表达式,并计算出结果。

技能目标:1. 学生培养逻辑思维能力,通过分析问题,能合理设计表达式并进行求值。

2. 学生通过实际操作,提高解决数学问题的计算速度和准确性。

3. 学生通过小组讨论和问题解决,提升合作能力和交流表达能力。

情感态度价值观目标:1. 学生培养对数学的兴趣,认识到数学在日常生活和未来学习中的重要性。

2. 学生在学习过程中树立正确的价值观,明白诚实求是的科学态度是学习数学的基础。

3. 学生通过解决表达式求值问题,增强自信心,培养勇于尝试和克服困难的积极态度。

课程性质分析:本课程为数学学科,针对五年级学生设计。

该阶段学生具备一定的数学基础和逻辑思维能力,需要通过表达式求值问题进一步巩固算术运算规则,提高解题能力。

学生特点分析:五年级学生处于好奇心强、求知欲旺的时期,他们喜欢探索和解决问题。

但同时,个别学生可能在数学学习上存在困难,需要教师关注并给予个性化指导。

教学要求:1. 教学内容紧密联系课本,确保学生能够掌握基础知识。

2. 教学过程中注重启发式教学,引导学生主动思考、积极参与。

3. 教学评价关注学生的过程表现,鼓励合作与交流,注重培养学生的综合能力。

二、教学内容本课程依据课程目标,结合课本第五章“数的运算”相关内容,组织以下教学大纲:1. 表达式求值基本概念:- 运算符的种类及优先级- 表达式的构成要素- 括号在表达式中的作用2. 算术运算规则:- 加、减、乘、除四则运算- 混合运算的表达式构建与简化- 乘方和开方的运算规则3. 表达式求值方法:- 逐步计算法- 分步骤代入法- 运用算术性质简化表达式4. 实际问题与表达式求值:- 根据实际问题编写表达式- 应用表达式求解问题- 分析实际问题的数量关系教学内容安排与进度:第一课时:表达式求值基本概念及运算符优先级第二课时:算术运算规则及表达式构建第三课时:表达式求值方法及简化技巧第四课时:实际问题与表达式求值的综合应用教材章节关联:《数学》五年级上册第五章“数的运算”:- 第1节 运算顺序与运算定律- 第2节 四则混合运算- 第3节 乘方与开方- 第4节 应用题与表达式求值三、教学方法为有效达成教学目标,本课程将采用以下多样化的教学方法:1. 讲授法:教师通过生动的语言和形象的比喻,对表达式求值的基本概念、运算规则进行讲解,确保学生掌握必要的理论知识。

表达式求值

表达式求值
任何一个表达式都是由操作数(operand)、运算 符(operator)和界限符(delimiter)组成, 其中, 操作数可以是常数也可以是被说明为变量或常量 的标识符; 运算符可以分为算术运算符、关系运算符和逻辑 运算符等三类; 界限符有左右括弧和表达式结束符等。 为了叙述简洁,在此仅讨论简单算术表达式。只 含加、减、乘、除4种运算符和圆括号。
(1)6 7 5 – 8 3 / * + (2)25 x + a a b + * b + *
问题2 问题2:如何对一个后缀表达式求值?
步骤: 1、读入表达式一个字符 2、若是操作数,压入栈,转4 3、若是运算符,从栈中弹出2个数,将运算结果再压入栈 4、若表达式输入完毕,栈顶即表达式值; 若表达式未输入完,转1 例 计算 4+3*5 后缀表达式:435*+
3 1 4 2 优先级,有时还要处理括号。
运算符的优先关系表
+ - × / ( ) + > > > > < > - > > > > < > × < < > > < > / < < > > < > ( < < < < < ) > > > > = >
后缀表达式:不包含括号,运算符放在两个运算
对象的后面,所有的计算按运算符出现的顺序,严 格从左向右进行。 如:2 1 + 3 *,对于的中缀表达式为(2 + 1) * 3
中缀表达式:在程序语Байду номын сангаас中,运算符位于两个操
作数中间的表达式称为是中缀表达式。P66 例子: 要对以下中缀表达式求值: 4+2×3 - 10/5 1 中缀表达式运算的规则: =4+6-10/5 (1)先乘除,后加减; 2 =4+6-2 (2)从左算到右; 3 =10-2 (3)先括号内,后括号外。 。 4 =8 + × - / 中缀表达式不仅要依赖运算符

数据结构实验报告--表达式求值

数据结构实验报告--表达式求值

void Initstack1(stack1 *s>
{
(*s>->base = (int *>malloc(SIZE * (sizeof(int>>>

(*s>->top = (*s>->base

(*s>->stacksize = INCREMENT 。
}
int Ifempty2(stack2 *s>
<6)中缀转后缀并计算模块:
( 三 > 详细设计
1.元素类型 , 结点类型和指针类型:
typedef struct{
int stacksize 。 int *base 。
int *top 。
}Sqstack1,*stack1 。
typedef struct{
int stacksize 。
char *base 。
{
if(((a=='*'>||(a=='/'>>&&((b=='+'>||(b=='-'>||(b=='#'>>>
5PCzVD7HxA
return '>'

else
return '<'

}
<4)运算符操作模块;
int Operate(int a,char b,int c>
{
int t 。
if(b == '+'> t = a + c
{

c语言算术表达式求值

c语言算术表达式求值

c语言算术表达式求值C语言是一种广泛应用的编程语言,其强大的算术表达式求值功能使其在科学计算、数据处理、游戏开发等领域有着重要的应用。

本文将介绍C语言中算术表达式求值的相关知识,包括运算符、运算符优先级、表达式求值的顺序等内容。

我们需要了解C语言中常用的算术运算符。

C语言支持的算术运算符包括加法(+)、减法(-)、乘法(*)、除法(/)和求余(%)等。

这些运算符用于对数值进行基本的加减乘除运算。

在C语言中,运算符的优先级决定了表达式求值的顺序。

常见的运算符优先级从高到低依次为:1. 括号(()):括号中的表达式具有最高的优先级,可以改变默认的运算次序。

2. 一元运算符:包括正号(+)和负号(-),用于表示正负数。

3. 乘法、除法和求余:乘法(*)、除法(/)和求余(%)的优先级相同,从左到右依次计算。

4. 加法和减法:加法(+)和减法(-)的优先级相同,从左到右依次计算。

在使用C语言进行算术表达式求值时,我们需要遵循这些运算符的优先级规则,以保证表达式的正确求值。

如果表达式中包含多个运算符,我们需要根据优先级确定运算的顺序,可以使用括号来改变默认的运算次序。

下面我们将通过几个例子来说明C语言中算术表达式求值的过程。

例1:求解一个简单的算术表达式假设我们需要计算表达式 3 + 4 * 2,根据运算符优先级规则,先计算乘法,再计算加法。

具体的求解过程如下:1. 计算4 * 2,得到8。

2. 计算3 + 8,得到11。

所以,表达式3 + 4 * 2的值为11。

例2:使用括号改变运算次序假设我们需要计算表达式(3 + 4) * 2,根据运算符优先级规则,先计算括号内的加法,再计算乘法。

具体的求解过程如下:1. 计算3 + 4,得到7。

2. 计算7 * 2,得到14。

所以,表达式(3 + 4) * 2的值为14。

通过以上两个例子,我们可以看到,C语言中的算术表达式求值是按照运算符优先级和运算次序进行的,遵循从左到右的计算规则。

表达式求值实验报告

表达式求值实验报告

表达式求值的类型定义与操作实现一、需求分析设计一个程序,演示用算符优先法对算术表达式求值的过程。

利用算符优先关系,实现对算术四则混合运算表达式的求值。

(1)输入的形式:表达式,例如2*(3+4)#;包含的运算符只能有'+' 、'-' 、'*' 、'/' 、'('、')';(2)输出的形式:运算结果,例如Answer is:77.000000;(3)程序所能达到的功能:对表达式求值并输出结果。

二、概要设计:本课程设计需要用到抽象数据类型栈存储表达式。

本部分给出栈的类型定义与表达式求值操作描述。

1、存储结构(顺序栈):typedef struct SqStack{SElemType *base;SElemType *top;int stacksize;}SqStack;2、基本操作:Status InitStack(SqStack &s)操作结果:初始化一个空栈s。

Status GetTop(SqStack s,SElemType &e)初始条件:栈s已存在。

操作结果:得到s的栈顶元素并用e带回。

Status Push(SqStack &s,SElemType e)初始条件:栈s已存在。

操作结果:向栈s中压入元素e。

Status Pop(SqStack &s,SElemType &e)初始条件:栈s已存在‘操作结果:弹出栈s栈顶元素,并用e带回。

Status In(char e)操作结果:判断e是否为7种运算符之一char Precede(char p,char c)操作结果:比较运算符p与运算符c的优先级。

SElemType Operate(SElemType x,char n,SElemType y)操作结果:计算x,y对运算符n的运算结果。

三、详细设计本部分主要给出表达式求值的实现算法1、初始化一个空栈sStatus InitStack(SqStack &s) //{s.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));if(!s.base)exit(OVERFLOW);s.top=s.base;s.stacksize=STACK_INIT_SIZE;return OK;}2、读取栈顶元素Status GetTop(SqStack s,SElemType &e){if(s.top==s.base)return ERROR;e=*(s.top-1);return OK;}3、向栈s中压入元素eStatus Push(SqStack &s,SElemType e){if(s.top-s.base>=s.stacksize){s.base=(SElemType*)realloc(s.base,(s.stacksize+STACKINCREMENT)*sizeof(SElemType));if(!s.base)exit(OVERFLOW);s.top=s.base+s.stacksize;s.stacksize+=STACKINCREMENT;}*s.top++=e;return OK;}4、弹出栈顶元素Status Pop(SqStack &s,SElemType &e) //{if(s.top==s.base)exit(OVERFLOW);e=* --s.top;return OK;}5、判断是否为7种运算符之一Status In(char e) / /{switch(e){case '+':case '-':case '*':case '/':case '(':case ')':case '#':return(1);break;default:return(0);}}6、比较两运算符优先级char Precede(char p,char c){ 'switch(p){case '+':case '-':switch(c){case '*':case '/':case '(':return '<';break;default:return '>';break;}break;case '*':case '/':switch(c){case '(':return '<';break;default:return '>';break;}break;case '(':switch(c){case ')':return '=';break;case '#':printf("ERROR!!\n");exit(OK);default:return '<';break;}break;case ')':switch(c){case '(':printf("ERROR!!\n");exit(OK);default:return '>';break;}break;case '#':switch(c){case ')':printf("ERROR!!\n");exit(OK);case '#':return '=';break;default:return '<';break;}break;}}7、四则运算SElemType Operate(SElemType x,char n,SElemType y) {SElemType e;switch(n){case '+':e=x+y;break;case '-':e=x-y;break;case '*':e=x*y;break;case '/':if(y==0){printf("分母不能为0!\n");exit(1);}else{e=x/y;break;}}return e;}8、主函数进行表达式求值void main(){SqStack OPTR,OPND;SElemType p,s,a,b,theta;char c;printf("请输入一个表达式并以'#'结束\n(只包括' +-*/' 和'('')'):\n");InitStack(OPTR);Push(OPTR,'#');InitStack(OPND);c=getchar();GetTop(OPTR,p);while(c!='#'||p!='#'){if(!In(c)){s=c-48;c=getchar();while(c>='0'&&c<='9'){s=s*10+(c-48);c=getchar();}Push(OPND,s);}else{switch(Precede(p,c)){case '<':Push(OPTR,c);c=getchar();break;case '=':Pop(OPTR,s);c=getchar();break;case '>':Pop(OPTR,theta);Pop(OPND,b);Pop(OPND,a);Push(OPND,Operate(a,theta,b));break;}GetTop(OPTR,p);}}//whileprintf("\n\n");GetTop(OPND,p);printf("Answer is:%f\n",p);getch();}四、调试分析1、初始化了一种类型的两个栈,分别用来存放数值和运算符。

表达式求值算法总结(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,求取中缀表达式,然后对中缀表达式求值。

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

字符串表达式求值(⽀持多种类型运算符)⼀、说明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;}上述代码的执⾏结果为:。

数据结构课程设计-表达式求值【完整版】

XXXXXX大学《数据结构》课程设计报告班级:学号:姓名:指导老师:目录一算术表达式求值一、需求分析二、程序得主要功能三、程序运行平台四、数据结构五、算法及时间复杂度六、测试用例七、程序源代码二感想体会与总结算术表达式求值一、需求分析一个算术表达式就是由操作数(operand)、运算符(operator)与界限符(delimiter)组成得。

假设操作数就是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号与表达式起始、结束符“#”,如:#(7+15)*(23—28/4)#。

引入表达式起始、结束符就是为了方便.编程利用“算符优先法”求算术表达式得值.二、程序得主要功能(1)从键盘读入一个合法得算术表达式,输出正确得结果。

(2)显示输入序列与栈得变化过程。

三、程序运行平台Visual C++6、0版本四、数据结构本程序得数据结构为栈。

(1)运算符栈部分:struct SqStack //定义栈{char *base; //栈底指针char *top; //栈顶指针intstacksize; //栈得长度};intInitStack (SqStack &s) //建立一个空栈S{if (!(s、base= (char *)malloc(50*sizeof(char))))exit(0);s、top=s、base;s、stacksize=50;return OK;}char GetTop(SqStack s,char &e) //运算符取栈顶元素{if (s、top==s、base) //栈为空得时候返回ERROR{ﻩ printf("运算符栈为空!\n");ﻩ return ERROR;}elsee=*(s、top-1); //栈不为空得时候用e做返回值,返回S得栈顶元素,并返回OK returnOK;}int Push(SqStack&s,char e) //运算符入栈{if (s、top—s、base >= s、stacksize)ﻩ{printf("运算符栈满!\n");ﻩs、base=(char*)realloc(s、base,(s、stacksize+5)*sizeof(char));//栈满得时候,追加5个存储空间if(!s、base)exit (OVERFLOW);s、top=s、base+s、stacksize;s、stacksize+=5;}ﻩ*(s、top)++=e;//把e入栈ﻩreturn OK;}int Pop(SqStack &s,char &e) //运算符出栈{if (s、top==s、base) //栈为空栈得时候,返回ERROR{printf("运算符栈为空!\n”);ﻩ return ERROR;}else{ﻩﻩe=*-—s、top;//栈不为空得时候用e做返回值,删除S得栈顶元素,并返回OK return OK;}}int StackTraverse(SqStack&s)//运算符栈得遍历{ﻩchar *t;ﻩt=s、base;ﻩif (s、top==s、base){ﻩ printf(”运算符栈为空!\n”); //栈为空栈得时候返回ERRORreturn ERROR;}while(t!=s、top){ﻩﻩprintf(" %c",*t); //栈不为空得时候依次取出栈内元素t++;ﻩ}return ERROR;}(2)数字栈部分:struct SqStackn//定义数栈{int *base; //栈底指针int*top; //栈顶指针int stacksize; //栈得长度};intInitStackn (SqStackn &s) //建立一个空栈S{s、base=(int*)malloc(50*sizeof(int));if(!s、base)exit(OVERFLOW);//存储分配失败s、top=s、base;s、stacksize=50;return OK;}int GetTopn(SqStackn s,int&e) //数栈取栈顶元素{if(s、top==s、base){printf("运算数栈为空!\n");//栈为空得时候返回ERRORﻩ return ERROR;}elseﻩe=*(s、top-1);//栈不为空得时候,用e作返回值,返回S得栈顶元素,并返回OKreturnOK;}int Pushn(SqStackn &s,int e) //数栈入栈{if(s、top—s、base>=s、stacksize){ﻩﻩprintf("运算数栈满!\n");//栈满得时候,追加5个存储空间ﻩs、base=(int*)realloc (s、base,(s、stacksize+5)*sizeof(int));if(!s、base) exit (OVERFLOW);ﻩs、top=s、base+s、stacksize;//插入元素e为新得栈顶元素s、stacksize+=5;}*(s、top)++=e; //栈顶指针变化returnOK;}int Popn(SqStackn &s,int &e)//数栈出栈{ﻩif (s、top==s、base){ﻩ printf("运算符栈为空!\n");//栈为空栈得视时候,返回ERRORﻩ return ERROR;ﻩ}else{ﻩﻩe=*—-s、top;//栈不空得时候,则删除S得栈顶元素,用e返回其值,并返回OK ﻩreturnOK;}}int StackTraversen(SqStackn &s)//数栈遍历{ﻩint*t;ﻩt=s、base ;ﻩif(s、top==s、base)ﻩ{printf("运算数栈为空!\n”);//栈为空栈得时候返回ERRORﻩ return ERROR;ﻩ}ﻩwhile(t!=s、top)ﻩ{printf(” %d”,*t); //栈不为空得时候依次输出t++;}return ERROR;}五、算法及时间复杂度1、算法:建立两个不同类型得空栈,先把一个‘#’压入运算符栈。

Java表达式求值、杨辉三角实验报告

一.实验目的实现杨辉三角和表达式的封装二.实验软件环境本实验是在MyEclipse 9.01M1编写和运行的三.实验内容(一)实验要求1. 输出杨辉三角前N项,N为参数2. 表达式求值:输入一个表达式,输出它的值,其中要用到java.util.Stack (二)实验代码程序代码:1)杨辉三角:/***功能:用二维数组实现杨辉三角*时间:2011-05-01**/package b1;import java.io.*;public class Pascal{public Pascal(){play();}public void play(){BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.print("请输入n值:");int n = 0;try {n = Integer.parseInt(br.readLine());} catch (NumberFormatException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}int array[][] = new int[n][2*n-1];//判断是否为奇数if( n%2 == 1 ){for(int i=1; i<=n; i++){for(int j=1; j<=2*n-1 ;j++){//首先给前5-i个元素赋值0if(j<=n-i)array[i-1][j-1] = 0;//输出第一个“1”和最后一个“1”else if((j==(n-i+1))||(j==n+i-1))array[i-1][j-1] = 1;else if((j < n+i-1)&&(j > n-i+1)){if((j-i)%2 == 1)array[i-1][j-1] = 0;elsearray[i-1][j-1] = array[i-2][j-2] + array[i-2][j];}}}}//为偶数所进行的操作else{for(int i=1; i<=n; i++){for(int j=1; j<=2*n-1; j++){//首先给前5-i个元素赋值0if(j<=n-i)array[i-1][j-1] = 0;//输出第一个“1”和最后一个“1”else if((j==(n-i+1))||(j==n+i-1))array[i-1][j-1] = 1;else if((j < n+i-1)&&(j > n-i+1)){if((j-i)%2 == 0)array[i-1][j-1] = 0;elsearray[i-1][j-1] = array[i-2][j-2] + array[i-2][j];}}}}/*输出数组*/for(int i=1; i<=n; i++){for(int j=1; j<=2*n-1; j++){if(array[i-1][j-1] == 0){System.out.print(" ");}elseSystem.out.print(array[i-1][j-1]);System.out.print(" ");}System.out.println();}}public static void main(String argc[]){Pascal p = new Pascal();}}2)表达式求值,代码如下:1)Stack类:用来存储表达式子元素的类,代码如下:package btwo;public class Stack {private int maxLen;private int size;private char c[];public Stack(int maxLen) {this.maxLen = maxLen;c = new char[maxLen];size = 0;}public void push(char v){c[size++] = v;}public char pop(){return c[--size];}public boolean isEmpty(){return size == 0;}}2)ExplainPostfix类:实现将输入的表达式转成后缀表达式,代码如下:package btwo; public class ExplainPostfix {String in; String out = "";Stack s;public ExplainPostfix(String in){System.out.println("计算表达式为:"+in);this.in = in;}public void display(){System.out.println("后缀表达式为:"+out);}//转换成后缀表达式public void toPraser(){s = new Stack(in.length());for(int i=0;i<in.length();i++){char c = in.charAt(i);switch(c){case'+':case'-':getOpter(c,1);break;case'*':case'/':getOpter(c,2);break;case'(':s.push(c);break;case')':getParen();break;default:out = out + c;}}while(!s.isEmpty()){out = out + s.pop();}}public void getOpter(char c,int prec1){ out = out + 'a';while(!s.isEmpty()){char optop = s.pop();if(optop == '('){s.push(optop);break;}else{int prec2 = 0;if(optop == '+' || optop== '-'){prec2 = 1;}else{prec2 = 2;}if(prec1>prec2){s.push(optop);break;}else{System.out.println("op:"+optop);out = out + optop;}}}s.push(c);}public void getParen(){while(!s.isEmpty()){char c = s.pop();if(c == '(')break;elseout = out + c;}}public static void main(String[] args) {ExplainPostfix p = newExplainPostfix("(11+2)*5");p.toPraser();p.display();}}3)CalculateExpression类:功能实现将后缀表达式进行计算,代码如下:package btwo;public class CalculateExpression {String in;Stack s; public CalculateExpression(String in) { this.in = in;}public CalculateExpression(){play();}public static void main(String args[]){ExplainPostfix p1 = newExplainPostfix("(21+4)*(1+3*2)");p1.toPraser();p1.display();CalculateExpression p = newCalculateExpression(p1.out);p.doPraser();p.display();}//开始计算后缀表达式public void doPraser(){while(true){int a,b,c,d;a = in.indexOf("+");b = in.indexOf("-");c = in.indexOf("*");d = in.indexOf("/");int n = Math.max(a, b);n = Math.max(n, c);n = Math.max(n, d);if(a != -1){n = a;}if(b<n && b!= -1){n = b;}if(c<n && c!= -1){n = c;}if(d<n && d!= -1){n =d;}if(a == -1 && b == -1 && c == -1 && d == -1){break;}String s1 = charAt(n-1);String s2 =charAt(n-2-s1.length());int v = 0;if(n == a){v = Integer.parseInt(s1) +Integer.parseInt(s2);}else if(n == b){v = Integer.parseInt(s2) -Integer.parseInt(s1);}else if(n == c){v = Integer.parseInt(s2) *Integer.parseInt(s1);}else{v = Integer.parseInt(s2) /Integer.parseInt(s1);}String s = ""+v;if(s.equals("0")){s = "";}else{s = s +"a";}in =in.substring(0,stIndexOf(s2))+v+in.substring(n+1,in.length());}}public void display(){System.out.println("结果为:"+in);}public String charAt(int i){String str = "";char c = in.charAt(i);if(c == '+' || c == '-' || c == '*' || c == '/'){str = str + c;return str;}else{while(c != 'a'){str = c + str ;if(i == 0){break;}c = in.charAt(--i);if(c == '+' || c == '-' || c == '*' || c == '/'){break;}}}return str;}}四.实验的结果及分析1. 杨辉三角结果:2. 算术表达式结果:五.实验心得体会试验后熟悉封装思想,使用基本Java算法。

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

《数据结构》实验报告
编号实验二实验项目表达式求值问题
学时数4课时指导教

冯韵


2011级计科
(2)班


1140901
02007


曾影
实验日期2013.9.3


优 良 中 及格

1、概述
我们在很早学习之前就学习表达式求值的计算,在计算机随处可见的今天,计算机已成为人们生活中不可缺少的使用工具。

人们就想利用计算机来进行表达式求值的运算。

我们对于表达式的求值,我们要熟悉表达式的求值顺序也就是运算规则:有括号先算括号内的,无括号时,先乘除再加减,对于相同级别的运算按从左到右次序计算,这是人们沿袭下来的使用的手工运算规则。

可是计算机对表达式的计算不是像我们手工运算的那样。

此程序是设计一个程序演示用算术优先法对算术表达式求值的过程。

深入了解栈和队列的特性,以便于解决实际问题能灵活运用它们,同时加深对这种结构的理解。

2、系统分析
2.1设计要求:
以字符序列的形式从终端输入语法正确的,不含变量的整型表达式,利用给定的算符优先关系,实现对算术四则混合运算表达式的求值,并演示在求值过程中运算栈,操作数栈,输入字符和主要操作的变化过程。

2.2分析:
人们在书写表达式时通常采用的是“中缀”表达式,就是将运算符放在两个操作数中间,但是这种表达形式对计算机处理来说是不大合适的,可以利用另外一种表达形式“后缀”表达式,就是将运算符紧跟在两个操作数的后面。

这种计算方法既简单又方便,特别是适合计算机的处理方式,用计算机来处理表达式求值问题首先要将人们习惯书写的中缀表达式转换成计算机容易处理的后缀表达式。

将中缀表达式转换成后缀表达式:这个过程需要运用到栈和队列,顺序扫描中缀表达式,当读到数字时直接将其送至输出队列中,当读到运算符时,将栈中所有优先级高于或等于该运算符的运算符弹出,送至输出队列中,再将当前运算符入栈,当读入左括号时即入栈,当读到右括号时,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列中,再删除栈中的左括号。

3、概要设计
3.1数据结构设计
任何一个表达式都是由操作符,运算符和界限符组成的。

我们分别用顺序栈来寄存表达式的操作数和运算符。

栈是限定于紧仅在表尾进行插入或删除操作的线性表。

顺序栈的存储结构是利用一组连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置,每当插入新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1。

3.2算法设计
为了实现算符优先算法。

可以使用两个工作栈和一个队列Q 。

一个称为OS ,用以寄存运算符,另一个称做VS ,用以寄存操作数或运算结果,队列Q 用来存放操作数。

1.首先置操作数栈为空栈,表达式起始符”#”为运算符栈的栈底元素;
2.依次读入表达式,若是操作符即进队列Q ,若是运算符则和QS 栈的栈顶运算符比较优先权后作相应的操作,直至整个表达式求值完毕(即QS 栈的栈顶元素和当前读入的字符均为”#”)。

3.3ADT 描述 ADT Stack{
数据对象:D={i a |i a ∈ElemSet,i=1,2,…,n, n ≧0} 数据对象:R1={<1,-i i a a >|1-i a ,D a i ∈,i=2,…,n} 约定n a 端为栈顶,i a 端为栈底。

基本操作: InitStack(&S)
操作结果:构造一个空栈S 。

GetTop(S)
初始条件:栈S 已存在。

操作结果:用P 返回S 的栈顶元素。

Push(&S ,ch)
初始条件:栈S 已存在。

操作结果:插入元素ch 为新的栈顶元素。

Pop(&S)
初始条件:栈S已存在。

操作结果:删除S的栈顶元素。

In(ch)
操作结果:判断字符是否是运算符,运算符即返回1。

Precede(c1, c2)
初始条件:c1,c2为运算符。

操作结果:判断运算符优先权,返回优先权高的。

Operate(a,op,b)
初始条件:a,b为整数,op为运算符。

操作结果:a与b进行运算,op为运算符,返回其值。

num(n)
操作结果:返回操作数的长度。

EvalExpr()
初始条件:输入表达式合法。

操作结果:返回表达式的最终结果。

}ADT Stack
函数之间的调用关系
main
表达式输入表达式转换表达式求值
输出输出
四、详细设计
4.1数据存储结构设计
1.定义队列类型:
typedef struct{
char data[100];
int front,rear;
}SeqQueue;
2.定义栈类型:
typedef struct{
DataType data[100];
int top;
}SeqStack;
4.2运算符优先级算法:
为了简化算法,把括号也作为运算符看待,并规定它的优先级最低,另外将表达式中的操作数规定为一位数字字符,运算符只包括+,-,*,/这四种。

int Priority(DataType op) {
switch(op){
case '(':
case '#':return 0;
case '-':
case '+':return 1;
case '*':
case '/':return 2;
}
return -1;
}
4.3 主要操作流程图及运输例子:
利用该算法对算术表达式9-(2+4*7)/5+3#求值的过程:
步骤 中缀表达式 运算符OS 栈 后缀表达式 主要操作 后缀表达式读入 运算结果栈VS
1
9-(2+4*7)/5+3# #

Push(OS,’#’)
9247*+5/-3+

2 -(2+4*7)/5+3# # 9 EnQueue(Q,’9’) 247*+5/-3+ 9
3 (2+4*7)/5+3# - 9 Push(OS,’-’) 47*+5/-3+ 2 9
4 2+4*7)/5+3# -( 9 Push(OS,’(’) 7*+5/-3+ 4 2 9
5 +4*7)/5+3# -( 9 2 EnQueue(Q,’2’) *+5/-3+ 7 4 2 9
6 4*7)/5+3# -(+ 9 2 Push(OS,’+’) +5/-3+ 28 2 9
7 *7)/5+3# -(+ 9 2 4 EnQueue(Q,’4’) 5/-3+ 30 9
8 7)/5+3# -(+*
9 2 4 Push(OS,’*’) /-3+ 5 30 9 9 /5+3# -(+* 9 2 4 7
EnQueue(Q,’7’)
-3+ 6 9 10 5+3# - 9 2 4 7 *+ 依次将*和+出栈再依次入队 3+ 3 11 +3# / 9 2 4 7 *+5 EnQueue(Q,’5’) + 3 3 12
3#
+
9 2 4 7
依次将/和-出栈

6
char c=表达式首字符
c=操作数 进入队列
和栈顶元素比较 如果‘>’进入栈 ‘=’ 进入栈 ‘ <’入队
return GetTop (VS)
五、运行与测试
六、总结与心得
1.照着书上的程序代码输入执行会发现这样的错误:
如图:
原来是整个程序少了一个函数,我自己将这个函数添加上去后程序能执行但是执行的结果只打印了后缀表达式。

*+5/-
再依次入队 13
#
+
9 2 4 7*+5/-3
EnQueue(Q,’3’)
14 空 空
9 2 4 7 *+5/-3+
将+出栈再入队列
添加函数为:
DataType DeQueue(SeqQueue *Q) {
char x;
if(QueueEmpty(*Q)) return 0;
else{
x=Q->data[Q->front ];
Q->front =(Q->front +1)%QueueSize;
return x;
}
} 出现的结果如图:
我在主函数添加了一些打印的代码后输出的结果为:代码为;
printf("**************************\n");
printf("表达式的运算结果为:%2d\n",CPostExp(Q)%48);
printf("\n************************\n");
printf("表达式的后缀表达式为:");
printf("\n");
printf("************************\n");
输出结果为:
通过这次实验我对数据结构有了更进一步的认识和了解也让我知道了要想学好数据结构重在实践,理论,实际应用相结合,提高了自己组织数据及编写大型程序的能力,培养了基本的、良好的程序设计技能力。

相关文档
最新文档