逆波兰表达式求值(实验报告及C 源码)
c++逆波兰式计算
c++逆波兰式计算C++逆波兰式计算是一种基于后缀表达式的计算方法。
逆波兰式也称为后缀表达式,其中操作符位于操作数之后。
下面我会从多个角度来解释逆波兰式计算。
1. 逆波兰式的转换:将中缀表达式转换为逆波兰式的过程称为逆波兰式的转换。
这个过程可以通过使用栈来实现。
具体步骤如下:从左到右扫描中缀表达式的每个元素。
如果遇到操作数,则直接输出到逆波兰式。
如果遇到操作符,则与栈顶操作符比较优先级。
如果栈顶操作符优先级高于当前操作符,则将栈顶操作符输出到逆波兰式,然后将当前操作符入栈;否则将当前操作符入栈。
如果遇到左括号,则将其入栈。
如果遇到右括号,则将栈顶操作符输出到逆波兰式,直到遇到左括号。
左括号出栈,但不输出到逆波兰式。
扫描结束后,将栈中剩余的操作符依次输出到逆波兰式。
2. 逆波兰式的计算:逆波兰式计算是通过对逆波兰式进行求值来得到结果的过程。
这个过程同样可以使用栈来实现。
具体步骤如下:从左到右扫描逆波兰式的每个元素。
如果遇到操作数,则入栈。
如果遇到操作符,则从栈中弹出两个操作数,进行相应的运算,并将结果入栈。
扫描结束后,栈中的唯一元素即为最终的结果。
3. C++实现逆波兰式计算:在C++中,可以使用栈来实现逆波兰式的计算。
具体步骤如下:定义一个栈来存储操作数。
从左到右扫描逆波兰式的每个元素。
如果遇到操作数,则将其转换为数字并入栈。
如果遇到操作符,则从栈中弹出两个操作数,进行相应的运算,并将结果入栈。
扫描结束后,栈中的唯一元素即为最终的结果。
总结:逆波兰式是一种基于后缀表达式的计算方法,可以通过转换中缀表达式得到。
逆波兰式计算可以使用栈来实现,通过扫描逆波兰式的每个元素,根据操作数和操作符进行相应的操作,最终得到计算结果。
在C++中,可以使用栈来实现逆波兰式的计算。
希望以上解释能够满足你的需求。
基于栈的后缀算术表达式求值c语言
基于栈的后缀算术表达式求值c语言1. 引言1.1 概述本文将讨论基于栈的后缀算术表达式求值的实现过程。
后缀算术表达式(也称为逆波兰表达式)是一种无需括号即可进行运算的表达式表示方法,它将操作符置于操作数之后。
相较于传统的中缀表达式,在计算机程序中处理后缀表达式更为高效和简洁。
1.2 文章结构文章分为五个主要部分:引言、栈的概念及原理、后缀算术表达式的定义和转换、基于栈的后缀算术表达式求值算法实现以及结论与总结。
在引言部分,我们将首先介绍本文的概述和目标,对后续内容进行简要说明。
1.3 目的通过本文,我们旨在让读者了解栈数据结构的基本概念和原理,并且掌握如何利用栈来实现对后缀算术表达式进行求值的算法。
同时,我们将介绍后缀算术表达式的定义和转换方法,并给出基于栈实现该计算方式的详细步骤与示例代码。
通过深入研究并学习这些内容,读者可以加深对栈数据结构和后缀算术表达式的理解,并且能够应用所学知识解决实际问题。
本文不仅适用于计算机科学或相关专业的学生,也适合对数据结构和算法感兴趣的读者阅读和学习。
2. 栈的概念及原理2.1 栈的定义栈是一种具有特定限制条件的线性数据结构,它具备“先进后出”(Last-In-First-Out,LIFO)的特性。
栈可以看作是一个容器,其中可以存储各种类型的数据。
与实际生活中的堆栈类似,栈只允许在其末尾进行插入和删除操作。
在栈中,最后加入的元素首先被访问和处理。
这是由于栈内元素之间的相对位置关系决定的。
插入操作称为“压栈”(Push),删除操作称为“弹栈”(Pop),而从栈顶读取元素或获取栈顶元素但不删除它称为“查看”(Peek)。
2.2 栈的基本操作推入元素:将一个元素添加到栈顶。
如果已经存在满员条件,则无法执行此操作。
弹出元素:从栈顶移除一个元素,并返回移除的值。
如果没有任何元素存在,则无法执行此操作。
查看栈顶元素:获取位于栈顶处的元素值,但不对其进行删除。
判断是否为空:检查栈是否为空。
C语言之逆波兰表达式完整代码(附算法)
C语言课程设计之逆波兰表达式//逆波兰表达式(后缀表达式)reverse polish notation//程序实现的功能是将中缀表达式转变为后缀表达式,再求出其值//主要运用的知识点有:isdigit函数,pow函数,system("cls")函数,堆栈,格式的强制转换#include<stdio.h>#include<ctype.h>#include<stdlib.h>#include<math.h>void shift( char notation[]); //中缀表达式转换为后缀表达式的转换函数float calculate(float a[][2],int k); //计算后缀表达式int judge(char notation[]); //判断输入的中缀表达式是否符合要求int grade(char a); //返回运算符的等级void display(float a[][2],int k); //在屏幕上显示后缀表达式//主函数void main(){char notation [100];char choice;do{printf("请输入正确的中缀表达式:\n");printf("例如:2*3+4/3-(2+1)\n");scanf("%s",¬ation);if(judge(notation)){shift(notation);}elseprintf("你的表达式有错误,请仔细检查!\n");fflush(stdin);printf("\n你是否需要继续计算(是输入Y/y,否输入其他任意键)\n");scanf("%c",&choice);getchar();system("cls");}while(choice=='Y'||choice=='y');printf("\n程序结束,谢谢使用!\n");}//判定函数int judge(char notation[]){int i,m,num=1,p1=0,p2=0;for(i=0;notation[i]!='\0';i++) //排除表达式外的字符{if(notation[i]!='('&¬ation[i]!=')'&¬ation[i]!='+'&¬ation[i]!='-'&¬ation[i]!='*'&¬ation[i]!='/'&&!isdigit(notation[i])&¬ation[i]!='.') {num=0;return num;}}if(notation[0]=='*'||notation[0]=='/'||notation[0]==')'||notation[0]=='.') //排除第一个字符为*,/,),.{num=0;return num;}for(i=0;notation[i]!='\0';i++) //排除'+','-','*','/','.'之间的连续出现以及'+','-','*','/','.'后面直接加')'{if(notation[i]!='('&¬ation[i]!=')'&&!isdigit(notation[i])){if(notation[i+1]!='('&&!isdigit(notation[i+1])){num=0;return num;}}if(notation[i]=='('&&(notation[i+1]==')'||notation[i+1]=='.'||notation[i+1]=='*'||notation[i+ 1]=='/')){ //排除'('和')','.','*','/'一起连用num=0;return num;}if(notation[i]==')'&&(notation[i+1]=='('||notation[i+1]=='.'))//排除')'和'(','.'一起连用{num=0;return num;}}for(i=0;notation[i]!='\0';i++) //小数位不得超过4位{if(notation[i]=='.'&¬ation[i+1]!='\0'&¬ation[i+2]!='\0'&¬ation[i+3]!='\0'&¬ation[i+4]!='\0'&¬ation[i+5]!='\0'){if(isdigit(notation[i+1])&&isdigit(notation[i+2])&&isdigit(notation[i+3])&&isdigit(notation[i+ 4])&&isdigit(notation[i+5])){num=0;return num;}}}for(i=0;notation[i]!='\0';i++) //排除一个小数中有两个小数点的情况{if(notation[i]=='.'){i++;while(isdigit(notation[i])){i++;}if(notation[i]=='.'){num=0;return 0;}}}for(i=0;notation[i]!='\0';i++) //排除')'后面不可以直接跟数字以及'('前面不可以加数字{if(notation[i]==')'&&isdigit(notation[i+1])){num=0;return num;}if(isdigit(notation[i])&¬ation[i+1]=='(' ){num=0;return num;}}for(i=0;notation[i]!='\0';i++) //约束数字的位数一共最多为七位{if(isdigit(notation[i])){m=0; //用来计数,数字的位数为7while(isdigit(notation[i])||notation[i]=='.'){i++;m++;if(notation[i]=='.'){m--;}}if(m>7){num=0;return num;}}}for(i=0;notation[i]!='\0';i++) //'('与')'需要配对存在{if(notation[i]=='(')p1++;if(notation[i]==')')p2++;if(p1!=p2){num=0;return num;}}return num;}//转换函数void shift( char notation[]){char s1[100];s1[0]='#';float s2[100][2]; //第一维放后缀表达式的元素,第二维表示小数点的位数以及是否是运算符int i=0,j=1,k=0,t=0;float sum,num1=0,num2=0; //num1为存储整数位num2为存储小数位while(notation[i]!='\0'){if(i==0&¬ation[i]=='+') //第一位为正号的情况{if(isdigit(notation[++i])){num1=0; //整数部分while(isdigit(notation[i])){num1=num1*10+(notation[i]-'0'); //notation[i]-'0'可以将字符转换为整数0~9i++;}num2=0; //小数部分t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float (num2+pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}}if(i==0&¬ation[i]=='-') //第一位为负号的情况,代码与正号类似{if(isdigit(notation[++i])){num1=0;while(isdigit(notation[i])){num1=(-1)*num1*10+(-1)*(notation[i]-'0');i++;}num2=0;t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float(num2+(-1)*pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}}if(isdigit(notation[i])) //当前字符为数字的情况与为正号的情况一样{num1=0;while(isdigit(notation[i])){num1=num1*10+(notation[i]-'0');i++;}num2=0;t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float(num2+pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}if(notation[i]=='+'||notation[i]=='-'||notation[i]=='*'||notation[i]=='/'){ //当前的字符为操作符时,如果s1的站定为'('则将字符直接送入s1if(s1[j-1]=='('){s1[j++]=notation[i++];}}if(notation[i]=='+'||notation[i]=='-'||notation[i]=='*'||notation[i]=='/'){ //当前字符为操作符时的普通的情况if(grade(notation[i])>grade(s1[j-1])){s1[j++]=notation[i++];}else{s2[k++][0]=s1[--j];s2[k-1][1]=-1;s1[j++]=notation[i++];}}if(notation[i]=='(') //当前字符为'('的情况{s1[j++]=notation[i++];if(notation[i]=='+') //'('后跟正号的情况{if(isdigit(notation[++i])){num1=0;while(isdigit(notation[i])){num1=num1*10+(notation[i]-'0');i++;}num2=0;t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float(num2+pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}}if(notation[i]=='-') //'('后跟负号的情况{if(isdigit(notation[++i])){num1=0;while(isdigit(notation[i])){num1=float((-1)*num1*10+(-1)*(notation[i]-'0'));i++;}num2=0;t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float(num2+(-1)*pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}}}if(notation[i]==')') //当前字符为')'的情况{while(s1[--j]!='('){s2[k++][0]=s1[j];s2[k-1][1]=-1;}i++;}}while(j>0&&s1[--j]!='#') //依次将s1中的除了'#'外的所有操作符出栈,相当于最后的扫尾工作{s2[k++][0]=s1[j];s2[k-1][1]=-1;}printf("\n后缀表达式(逆波兰表达式):\n");display(s2,k-1);printf("\n表达式的值为:\n");sum=calculate(s2,k-1);printf("%7.4f",sum);}//计算函数float calculate(float a[][2],int k){int i,t=0,j=k;float b[100][2],c[100];for(i=k;i>=0;i--){b[i][0]=a[k-i][0];b[i][1]=a[k-i][1];}i=k;while(j>=0){if(b[i][1]!=-1){c[t]=float (b[i][0]);j--;i--;t++;}if(b[i][1]==-1) //每当遇到一个运算符则将栈最上面的两个数出栈进行运算,然后再入栈{if(int(b[i][0])=='+'){c[t-2]=float (c[t-2]+c[t-1]);}if(int(b[i][0])=='-'){c[t-2]=float (c[t-2]-c[t-1]);}if(int(b[i][0])=='*'){c[t-2]=float (c[t-2]*c[t-1]);}if(int(b[i][0])=='/'){c[t-2]= float (c[t-2]/c[t-1]);}j--;i--;t--;}}return c[0]; //运算到最后,栈中的元素即为结果}//等级函数int grade(char a) //按照运算符的优先级{if(a=='#')return 0;if(a=='(')return 1;if(a=='-'||a=='+')return 2;if(a=='*'||a=='/')return 3;if(a==')')return 4;elsereturn 5;}//显示函数void display(float a[][2],int k){int i;for(i=0;i<=k;i++){if(a[i][1]==0)printf(" %d",int(a[i][0]));if(a[i][1]==1)printf(" %7.1f",a[i][0]);if(a[i][1]==2)printf(" %7.2f",a[i][0]);if(a[i][1]==3)printf(" %7.3f",a[i][0]);if(a[i][1]==4)printf(" %7.4f",a[i][0]);if(a[i][1]==-1)printf(" %c",int (a[i][0]));}}算法实现一个表达式E的后缀形式可以如下定义:(1)如果E是一个变量或常量,则E的后缀式是E本身。
逆波兰运算c语言实现
逆波兰运算c语言实现以逆波兰运算C语言实现为标题逆波兰表达式(Reverse Polish Notation,简称RPN)是一种数学表达式的书写方式,也是一种计算机科学中常用的运算方式。
在逆波兰表达式中,操作符位于操作数的后面,这样可以避免使用括号,使得表达式更加简洁明了。
本文将介绍如何使用C语言实现逆波兰运算。
1. 逆波兰表达式的基本概念逆波兰表达式的基本原则是将操作符放在操作数的后面,以此来表示运算顺序。
例如,将中缀表达式"3 + 4"转换为逆波兰表达式的结果为"3 4 +"。
在逆波兰表达式中,每个操作数和操作符之间都用空格分隔开。
2. 实现逆波兰表达式的算法为了实现逆波兰表达式的计算,我们可以使用栈来存储操作数和操作符。
遍历逆波兰表达式的每一个元素,如果是操作数,就将其入栈;如果是操作符,就从栈中弹出两个操作数进行运算,并将结果再次入栈。
最后,栈中剩下的元素即为最终的计算结果。
3. C语言实现逆波兰表达式的代码下面是一个简单的C语言实现逆波兰表达式的代码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_STACK_SIZE 100typedef struct {int top;int stack[MAX_STACK_SIZE];} Stack;void push(Stack *s, int value) {if (s->top < MAX_STACK_SIZE) { s->stack[s->top++] = value; } else {printf("Stack Overflow\n"); exit(1);}}int pop(Stack *s) {if (s->top > 0) {return s->stack[--s->top]; } else {printf("Stack Underflow\n");exit(1);}}int calculate(int a, int b, char operator) { switch (operator) {case '+':return a + b;case '-':return a - b;case '*':return a * b;case '/':return a / b;default:printf("Invalid Operator\n");exit(1);}}int evaluateRPN(char *rpn) {Stack s;int len = strlen(rpn);for (int i = 0; i < len; i++) {if (isdigit(rpn[i])) {push(&s, rpn[i] - '0');} else if (rpn[i] == ' ') {continue;} else {int b = pop(&s);int a = pop(&s);int result = calculate(a, b, rpn[i]); push(&s, result);}}return pop(&s);}int main() {char rpn[] = "3 4 +";int result = evaluateRPN(rpn);printf("The result is: %d\n", result);}```4. 运行结果分析以上代码中的逆波兰表达式为"3 4 +",表示的是3加4。
c语言实现逆波兰表达式!
}else if(a[i] == ' '){ i++;
}else if(a[i] == '+'){ x1 = operNum[--top]; x2 = operNum[--top]; operNum[top++] = x1 + x2; i++;
博客园 用户登录 代码改变世界 密码登录 短信登录 忘记登录用户名 忘记密码 记住我 登录 第三方登录/注册 没有账户, 立即注册
c语 言 实 现 逆 波 兰 表 达 式 !
C语言实现逆波兰表达式 (栈的应用 )
#include<iostream> #include<cstdio> using namespace std; const int MAXSIZE = 110; char a[MAXSIZE]; double operNum[MAXSIZE]; double getSum(int* i){//地址传递,可以在边求值时边改变i的原值。如若是值传递,会导致值的重复算
}else if(a[i] == '-'){ x1 = operNum[--top]; x2 = operNum[--top]; operNum[top++] = x2 - x1; i++;
}else if(a[i] == '*'){ x1 = operNum[--top]; x2 = operNum[--top]; operNum[top++] = x1 * x2; i++;
对逆波兰式计算的程序设计
数据结构作业报告逆波兰式的计算一题目内容逆波兰式也叫后缀表达式(将运算符写在操作数之后)如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+(a+b)*c-(a+b)/e的后缀表达式为:(a+b)*c-(a+b)/e→((a+b)*c)((a+b)/e)-→((a+b)c*)((a+b)e/)-→(ab+c*)(ab+e/)-→ab+c*ab+e/-计算给出的逆波兰式(假设条件:逆波兰表达式由单字母变量和双目四则运算符构成,以’#‘作为结束标志)。
二题目分析逆波兰式即后缀表达式,运算符置于两个操作数之后。
运算实应从前往后依次读出两个运算数,与这两个运算数之后的运算符进行计算,然后再从前往后提取两个操作数,再从之后提取对应的运算符,直到计算完毕。
这与栈的功能相一致,建立一个栈结构,将表达式的各个字符依次读取,若是数字则放入栈中,,若是操作符则从栈中提取两个数字进行运算,将运算结果加入到栈中,直至运算完毕。
三程序描述首先定义相关数值,建立栈结构的数据类型typedef struct{SElemType *base;SElemType *top;int stacksize;}SqStack;之后是各个对栈的操作函数Status InitStack(SqStack &S){S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElem Type));if(!S.base)exit(OVERFLOW);S.top=S.base;S.stacksize=STACK_INIT_SIZE;return OK;}//建立空栈Status Push(SqStack &S,SElemType e){if(S.top-S.base>=S.stacksize){S.base=(SElemType*)malloc(S.base,(S.stacksize+STACKINCREME NT)*sizeof(SElemTYpe));if(!S.base)exit(OVERFLOW);S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;return OK;}//将栈顶元素输出到元素e之中Status Pop(SqStack &S,SElemType e) {if(S.top==S.base)return ERROR;e=*--S.top;return OK;}//将元素e加入到栈之中程序最重要的操作函数如下(进行计算操作):char CalVal_InverPoland(char Buffer[]){Stack Opnd;InitStack(Opnd);int i=0;char c;ElemType e1,e2;while(Buffer[i]!='#'){if(!IsOperator(Buffer[i])){Push(Opnd,Buffer[i]);}else{Pop(Opnd,e2);Pop(Opnd,e1);c=Cal(e1,Buffer[i],e2);Push(Opnd,c);}i++;}return c;}while循环中是对表达式各字符的判断和计算过程,如果是数字则加入栈中,是操作符则从栈中提取两数据进行计算,之后将计算结果加入到栈中,直至遇到表达式结束标志’#’则结束运算,栈中数字则为计算结果。
实验2 逆波兰表达式求值
1、以字符串方式输入一逆波兰表达式;
2、对逆波兰表达式进行分解、运算,并输出运算结果。
实现提示:
采用栈存储扫描到的运算量或运算的中间结果。
运行环境:
Microsoft visual C++6.0控制台
问题分析:
逆波兰表达式求值可以利用堆栈的数据结构思想进行实现。数组结构即可完成堆栈数据的相同的功能。具体是根据你逆波兰表达式中的操作符提取操作数(相当于堆栈中的pop操作),进行运算之后把结果存回数组(相当于push操作),通过不断的出栈、入栈操作最终栈中保存的数据则为逆波兰表达式的结果。
如果对应操作符不能提取到所需的操作数,即i-1<0,表明输入的逆波兰表达式是错误的表达式,输出提示,并重新输入。此过程通过增加一个flag标识,当flag=1表示有错,flag=0表示表达式正确。
本实验将逆波兰表达式求值定义为一个函数,在主函数中调用该函数,并把结果保存在其参数中,然后打印输出结果。
jj++;
n2++;
switch(*p)//利用该操作符进行对应的操作,并用结果的替代数组a中的倒数第//二个值。
{
case '+':
if(i-1<0)
{flag=1;break;}
answer=a[i]+a[i-1];a[i-1]=answer;i--;n1--; flag=0;break;
case '-':
实验2逆波兰表达式求值
By 20110149杨付乾11级茅信1班
问题描述:
逆波兰表达式也称后缀式,是一种运算量在前,运算符在后的表示方式;运算主要特点是不必考虑运算符的优先顺序。
C语言简单计算器原理——表达式求值(采用逆波兰表达式和栈结合)
C语⾔简单计算器原理——表达式求值(采⽤逆波兰表达式和栈
结合)
表达式的求解的关键是将其转换成逆波兰表达式(即后缀表达式,如1+2*3它的逆波兰表达式为123*+),在后缀表达式中已经考虑了运算符的优先级,
没有括号,只有操作数和运算符。
算术表达式转换成后缀表达式⽅法如下:
依次从键盘输⼊表达式的字符ch,对于每个ch:
(1)若ch为数字则直接将其放⼊后缀数组exp中并以#号标记数值串结束。
(2)若ch为"(",则直接将其压⼊字符栈op中。
(3)若ch为")",则将栈中"("以前的字符依次全部删除并将其放⼊后缀数组exp中,然后再将字符ch放⼊字符栈op中。
(4)若ch为"+"."-",则将栈中"("以前的运算符依次全部删除并将其放⼊后缀数组exp中,然后再将ch放⼊op栈中。
(5)若ch为"*"."/",则将栈顶连续的"*"."/"删除,并放⼊后缀数组exp中,然后将ch放⼊op栈中。
(6)若字符串str扫描完毕,则将栈中所有运算符删除并放⼊后缀数组exp,最后在后缀数组exp中便可得到后缀表达式。
在对后缀表达式求值时要⽤到⼀个数值栈st,在后缀数组exp中从头开始扫描,若是数字则将其放⼊数值栈中,
若遇到字符就进⾏两次退栈,并将运算结果再放⼊栈中,如此重复下去,最后当后缀数组扫描完后数值栈st的栈顶元素便是所要求的表达式的值。
逆波兰式的转化与求值 栈与队列 实验报告
逆波兰式实验报告2011.4.15实验题目:逆波兰式的转化与求值实验目的:了解并运用栈与队列。
在程序中将非逆波兰式表示的算术表达式转换为用逆波兰式表示,并计算用逆波兰式来表示的算术表达式的值。
验证刚学的栈和队列的理论,巩固知识并加深理解。
实验内容:一、抽象数学模型:逆波兰式转化程序流程:逆波兰式求值程序流程:二、详细算法描述:逆波兰式计算://先初始化一个栈s,并将左括号'('压栈//从左至右对表达式进行扫描,依次存入字符串s1中//若遇到数字则存入字符串s2中//若遇到右括号则将栈s中的元素弹出放入s2中直到遇到左括号'(',并将左括号出栈//若遇到左括号则直接进栈//若遇到运算符则需比较其与栈顶元素优先级顺序,若大于则直接入栈,否则弹出栈顶元素存入s2中直到运算符的优先级//低于栈顶元素并将其压栈//当遇到'#'时表明表达式以全部输入,此时将栈s中元素弹出并放入s2中,直至遇到左括号')'//将'#'放入s2作为表达式结束标志,表达式转换为逆波兰式(后缀表达式)后缀表达式求值算法描述//先初始化一个栈s//从左至右对s2进行扫描//若遇到数字字符则压入栈s//若遇到运算符则将栈s中元素依次弹出两个进行运算,将运算结果压栈//当遇到'#'时表达式结束,此时弹出栈顶元素即为表达式的值三、程序清单:(见附录)四、运行结果(截图):运行结果分析:将运算对象写在前面,而把运算符号写在后面。
程序采用逆波兰式可以很好的表示简单算术表达式,易于计算机处理表达式。
由运行结果可知,可以正确地把算术表达式转化为后缀表达式且能够正确计算出表达式的值五、调试分析和体会:(一)、实验程序编写过程中运用了栈的相关知识,通过栈实现逆波兰式的转化和计算。
(二)、利用栈,巧妙地把表达式转化为后缀表达式从而大大简化翻译过程,同时在对后缀表达式进行计算时也方便了计算。
(编译原理)逆波兰式算法的源代码
(编译原理)逆波兰式算法的源代码一.实验目的1.深入理解算符优先分析法2.掌握FirstVt和LastVt集合的求法有算符优先关系表的求法3.掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化二.实验内容及要求将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。
程序输入/输出示例:输出的格式如下:(1)(2)输入一以#结束的中缀表达式(包括+—*/()数字#)(3)(4)逆波兰式备注:(1)在生成的逆波兰式中如果两个数相连则用&分隔,如28和68,中间用&分隔;串。
注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、数字,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。
同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;三.实验过程1、逆波兰式定义将运算对象写在前面,而把运算符号写在后面。
用这种表示法表示的表达式也称做后缀式。
逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。
采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。
2、产生逆波兰式的前提中缀算术表达式3、逆波兰式生成的实验设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
逆波兰(加、减、乘、除、括号)表达式原理及C++代码实现
逆波兰(加、减、乘、除、括号)表达式原理及C++代码实现当我们输⼊⼀个数学表达式,是中缀表达式,我们⾸先转换为后缀表达式(逆波兰表达式),然后再进⾏求值。
代码思路:(1)⾸先对输⼊的中缀表达式合法性进⾏判断,bool isStringLegal(const char* str); 函数实现。
(2)然后把中缀表达式转换为后缀表达式。
(3)根据后缀表达式求出结果,double getTheResult(vector<string> &vec);函数实现。
注意:表达式的运算符可以输⼊加、减、乘、除、括号,输⼊的数据为整形数据,计算结果为double型数据。
1 #include <iostream>2 #include <math.h>3 #include <map>4 #include <vector>5 #include <string.h>6 #include <memory>7 #include <string>8 #include <stdio.h>9 #include <stack>10 #include <stdlib.h>1112using namespace std;1314#define MAX_STRING_LENGTH 1001516/* 解析当前的整形数据,并把整形数据转换为string型 */17string analyData(const char* str, int &i);1819/* 根据逆波兰表达式求表达式的值 */20double getTheResult(vector<string> &vec);2122/* 判断该字符是否是 + - * / ( ) */23bool isCalChar(const char ch);2425/* 判断输⼊的中缀表达式是否合法 */26bool isStringLegal(const char* str);27282930/* 解析当前的整形数据,并把整形数据转换为string型 */31string analyData(const char* str, int &i)32 {33int temp = i++;34while(str[i] >= '0' && str[i] <= '9' && str[i] != '\0')35 {36 i++;37 }3839string s(str+temp,str+i);4041return s;42 }4344/* 根据逆波兰表达式求表达式的值 */45double getTheResult(vector<string> &vec)46 {47 vector<string>::iterator it;48 stack<double> sta;4950string strTemp;51double d = 0, d1 = 0, d2 = 0;5253for(it = vec.begin(); it != vec.end(); it++)54 {55 strTemp = (*it);5657if(strTemp == "+")58 {59 d1 = sta.top();60 sta.pop();6162 d2 = sta.top();63 sta.pop();6465 d = d1 + d2;66 sta.push(d);67 }68else if(strTemp == "-")69 {70 d1 = sta.top();71 sta.pop();7273 d2 = sta.top();74 sta.pop();7576 d = d2 - d1;77 sta.push(d);78 }79else if(strTemp == "*")80 {81 d1 = sta.top();82 sta.pop();8384 d2 = sta.top();85 sta.pop();8687 d = d2 * d1;88 sta.push(d);89 }90else if(strTemp == "/")91 {92 d1 = sta.top();93 sta.pop();9495 d2 = sta.top();96 sta.pop();9798 d = d2 / d1;99 sta.push(d);100 }101else102 {103const char *p = strTemp.c_str();104 d = atoi(p);105 sta.push(d);106 }107 }108return sta.top();109 }110111/* 判断该字符是否是 + - * / ( ) */112bool isCalChar(const char ch)113 {114if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')') 115 {116return true;117 }118119return false;120 }121/* 判断输⼊的中缀表达式是否合法 */122bool isStringLegal(const char* str)123 {124/* 判断是否是空串 */125if(NULL == str)126 {127return false;128 }129130int len = strlen(str);131int i = 0;132int flag = 0;133134/* 字符串的开头和末尾是否是数字 */135if(str[0] > '9' || str[0] < '0' || str[len-1] > '9' || str[len-1] < '0')136 {137return false;138 }139140141for(i = 0; str[i] != '\0'; i++)142 {143/* 是否有除了加减乘除括号之外的字符 */144if(isCalChar(str[i]) == false)145 {146return false;147 }148149/* 判断是否有两个连续的符号 */150if(i < len-1 && isCalChar(str[i]) == true)151 {152if(isCalChar(str[i+1]) == true)153 {154return false;155 }156157 }158159/* 判断括号是否成对 */160if(str[i] == '(')161 {162 flag++;163 }164else if(str[i] == ')')165 {166 flag--;167 }168169/* 判断是否出现 )( 这样的情况 */170if(flag < 0)171 {172return false;173 }174 }175176/* 判断括号是否匹配 */177if(flag != 0)178 {179return false;180 }181182return true;183 }184185int main(void)186 {187char str[MAX_STRING_LENGTH] = {0};188int i = 0;189string data;190191/* 存放运算符表达式的栈 */192 stack<char> oper_char;193194/* 存放后缀表达式 */195 vector<string> post_str;196197/* 输⼊中缀的表达式 */198 gets(str);199200/* 判断输⼊的中缀表达式是否合法 */201if(isStringLegal(str) != true)202 {203 cout << "This expression is not legal." << endl; 204 }205else206 {207/* 将中缀表达式转换为后缀表达式 */208for(i = 0; str[i] != '\0'; i++)209 {210/* 如果该字符为数字,解析该数字,并压⼊栈 */ 211if(str[i] >= '0' && str[i] <= '9')212 {213 data = analyData(str,i);214 post_str.push_back(data);215 i--;216 }217else if(str[i] == '(')218 {219 oper_char.push(str[i]);220 }221else if(str[i] == ')')222 {223char chtemp[2] = {0};224225 chtemp[0] = oper_char.top();226227while(chtemp[0] != '(')228 {229string strtemp(chtemp);230 post_str.push_back(strtemp);231 oper_char.pop();232233 chtemp[0] = oper_char.top();234 }235 oper_char.pop();236 }237else if(str[i] == '+' || str[i] == '-')238 {239char chtemp[2] = {0};240241/* 全部出栈,但是碰到 '('就要停⽌出栈 */242while(oper_char.size() != 0)243 {244 chtemp[0] = oper_char.top();245if(chtemp[0] == '(')246 {247break;248 }249250 oper_char.pop();251252string strtemp(chtemp);253 post_str.push_back(strtemp);254 }255256/*将当前的表达式符号⼊栈*/257 oper_char.push(str[i]);258 }259else if(str[i] == '*' || str[i] == '/')260 {261char chtemp[2] = {0};262while(oper_char.size() != 0)263 {264 chtemp[0] = oper_char.top();265if(chtemp[0] == '(' || chtemp[0] == '+' || chtemp[0] == '-') 266 {267break;268 }269else270 {271 oper_char.pop();272273string strtemp(chtemp);274 post_str.push_back(strtemp);275 }276 }277278/*将当前的表达式符号⼊栈*/279 oper_char.push(str[i]);280 }281 }282283/* 存放表达式的栈可能还有数据 */284while(!oper_char.empty())285 {286char chtemp[2] = {0};287 chtemp[0] = oper_char.top();288 oper_char.pop();289290string strtemp(chtemp);291 post_str.push_back(strtemp);292 }293294/* 把逆波兰表达式求值 */295 cout << getTheResult(post_str) << endl;296 }297298return0;299 }。
数据结构实验报告——逆波兰表达式求值
实验三逆波兰表达式求值一.问题描述:读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。
二.需求分析:1. 本程序需要基于堆栈的基本操作来实现逆波兰表达式的求值。
2.若表达式正确,界面自动输出后缀表达式的值,否则输出表达式错误的信息,将结果置为0。
3.操作数和操作符均由键盘键入。
4.输入输入一个后缀表达式2 3 * 1 - #输出结果5三.概要设计由于操作的事一串字符,所以首先选择一个字符数组存储该串字符,直接使用编译器自带的字符数组。
由于计算后缀表达式时,具有先进后出的规律,故而考虑使用堆栈其ADT Stack{操作对象:字符,整数,浮点数基本操作:Stack(int size);//构造大小为size的堆栈~Stack();//撤销堆栈Bool IsEmpty();//是否为空,是返回true,否则返回falseBool IsFull();//是否为满,是返回true,否则返回falseVoid Push(T X);//将x压入堆栈Void Pop(T &x);//弹出栈顶元素,并用x保存对于计算后缀表达式的值的算法:首先假设此表达式正确从字符串第一个开始扫描,遇到运算数就先转化成为数值然后压入堆栈中,如遇到运算符则弹出堆栈上面的两个元素,并进行对应的运算,将得到的值压入栈中,直到最后一个字符为止。
对于表达式错误:返回01、小数缺少整数部分:如 .999未检测到数,而是直接检测到小数点2、运算符过多:2 3*-弹出一个数后堆栈便空3、运算数过多:3 7*0最后堆栈不空四.源程序:/*Name: 逆波兰表达式求值Copyright: WCH466-Experiment-3Author: wch466Date: 02/04/12 22:59Description: 读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。
*/// Copyright: WCH466-Experiment-3#include<iostream>#include<string>#include<cmath>using namespace std;class Astack{private:int size;int top;float *list;bool g;public:Astack(int se=4){size=se;top=0;list=new float [size];g=1;}~Astack() {delete [] list;}void push(const float& it) //入{if(top==size) return;list[top++]=it;}float pop(){if(top==0) {g=0;return 0;} //g=0代表表达式错误(运算符多了)return list[--top];}bool judge(){return g;}int length() const {/*cout<<"length of list is "<<top<<endl; */return top;}};// Copyright: WCH466-Experiment-3void Pretreatstr(const char *a) //预处理字符{ int i=0,g=1,s=1,size=strlen(a),k=0;float num=0,in=0,x,y,de=0; //stand for integer,decimalAstack t(size);for(i=0;i<size;i++){ if(a[i]=='#') break;if(a[i]>47){ s=1; //有数if(g)in=in*10+a[i]-48; //提取整数部分else //小数处理{ de=(a[i]-48)*pow(0.1,k++)+de;}}if(a[i]==46){if(g==0) {cout<<"小数点多余!";return ;} g=0;k=1;} //有小数if(a[i]==42||a[i]==43||a[i]==45||a[i]==47||a[i]==' '){if(s) // s=0 代表没数{t.push(in+de);in=0;de=0;g=1;s=0;}/*cout<<"插入:"<<in+de<<endl;*/ if(a[i]!=' ') { y=t.pop(); x=t.pop();}if(a[i]=='+') t.push(x+y);if(a[i]=='-') t.push(x-y);if(a[i]=='*') t.push(x*y);if(a[i]=='/') {if(y==0) {cout<<"分母为零!"<<endl; return;} t.push(x/y); }}}if(t.length()==1&&t.judge()&&a[i-1]<48) //最后一个字符不能为num{ cout<<"表达式的答案是:"<<int(t.pop()*100)/100.0<<endl;}elsecout<<"表达式错误"<<endl;};// Copyright: WCH466-Experiment-3int main(){char s[100];while(gets(s))Pretreatstr(s);system("pause");return 0;}五.测试结果:六.实验心得:1. 通过本次试验,我发现自己分析问题不是很全面,忽略掉一些细节。
(编译原理)逆波兰式算法地源代码
一.实验目的1.深入理解算符优先分析法2.掌握FirstVt和LastVt集合的求法有算符优先关系表的求法3.掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化二.实验内容及要求将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。
程序输入/输出示例:输出的格式如下:(1)(2)输入一以#结束的中缀表达式(包括+—*/()数字#)(3)(4)逆波兰式备注:(1)在生成的逆波兰式中如果两个数相连则用&分隔,如28和68,中间用&分隔;注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、数字,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。
同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;三.实验过程1、逆波兰式定义将运算对象写在前面,而把运算符号写在后面。
用这种表示法表示的表达式也称做后缀式。
逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。
采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。
2、产生逆波兰式的前提中缀算术表达式3、逆波兰式生成的实验设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。
逆波兰表达式 计算器 实验报告
计算机科学与工程学院综合设计报告说明:1、报告中的第一、二、三项由指导教师在综合设计开始前填写并发给每个学生;四、五两项(中英文摘要)由学生在完成综合设计后填写。
2、学生成绩由指导教师根据学生的设计情况给出各项分值及总评成绩。
3、指导教师评语一栏由指导教师就学生在整个设计期间的平时表现、设计完成情况、报告的质量及答辩情况,给出客观、全面的评价。
4、所有学生必须参加综合设计的答辩环节,凡不参加答辩者,其成绩一律按不及格处理。
答辩小组成员应由2人及以上教师组成。
5、报告正文字数一般应不少于5000字,也可由指导教师根据本门综合设计的情况另行规定。
6、平时表现成绩低于6分的学生,其综合设计成绩按不及格处理。
7、此表格式为武汉工程大学计算机科学与工程学院提供的基本格式(适用于学院各类综合设计),各教研室可根据本门综合设计的特点及内容做适当的答辩记录表目录摘要 (II)Abstract (II)第一章课题背景 (1)1.1 课题背景 (1)1.2 课程设计目的 (1)第二章设计简介及设计方案论述 (2)2.1 工作原理 (2)2.2.1要求 (2)2.2.2任务 (3)第三章详细设计 (4)3.1流程图 (4)3.2 设计的细节 (4)3.3 由后缀表达式计算中缀表达式原理 (6)3.4 算法描述 (6)第四章设计结果及分析 (7)4.1输入不同表达式验证程序的正确性 (7)致谢 (10)参考文献 (11)摘要本课程设计将实现一个简单计算器。
在功能上尽量模仿windows的计算器。
系统界面不做牵制要求。
该程序能实现标准型中+、-、*、/、^(乘方)、%(求余)、(、)的混合运算表达式(一般意义上的中缀表达式),将其转换成逆序波兰表达式(后缀表达式)并计算输出结果。
在进行运算后可以选择继续运算或者结束当前运算。
即时准确地获得需要的计算的结果,充分降低了数字计算的难度和节约了时间,对人们的生活有一定的帮助。
在课程设计中,系统开发平台为Windows XP,程序设计设计语言采用Visual C++,在程序设计中,采用了结构化与面向对象两种解决问题的方法。
逆波兰表达式求值(实验报告及C源码)
逆波兰表达式求值一、需求分析1、从键盘中输入一个后缀表达式,该表示包括加减乘除等操作符,以及正整数作为操作数等。
2、用堆栈来实现3、测试数据输入:2 3 * 1 – #输出:2 3 * 1 -- =5二、概要设计抽象数据类型需要一个浮点数栈来存储还没有计算的浮点数或者运算的结果。
ADT Stack数据成员:int size; int top; //分别用于存储栈大小、栈顶位置float *listArray;//存储浮点型数字的数组成员函数:bool push(float it);bool pop(float& it);bool isEmpty(); //判断栈为空bool isOne();//判断栈是否只有一个元素算法的基本思想1. 逐一扫描字符串,用ascii码进行判断,如果该字符是数字,则利用x=x*10+str[i]-48将数据由字符类型转换为浮点型数据;2. 如果字符是‘.’,则将‘.’转化为小数点,并将‘.’后的数据转化为小数部分;3. 遇到空格前是数据的,将x押入栈;4. 如果该字符是’+’,’-’,’*’或’/’,判断栈里的元素是否少于两个个,如果少于两个,报错;如果大于等于两个,就弹出两个数据,并进行相应的计算;程序的流程输入字符串,程序对字符串依次扫描。
扫描一位,处理一位。
扫描完成后,判断栈里是不是只有一个数据,若是,得到正确结果;若不是,则表达式出错。
三、详细设计物理数据类型用浮点数类型的栈存储运算中要用的数据,需要入栈、出栈,故设计如下的浮点类型的栈:class Stack{private:int size;int top;float *listArray;public:Stack(int sz=20);~Stack();bool push(float it);//入栈bool pop(float& it);//出栈bool isEmpty();//判断栈是否为空bool isOne(); //判断栈里是否只有且仅有一个元素};成员函数的函数体Stack::Stack(int sz) //栈构造函数{size=sz;top=0;listArray=new float[size]; }bool Stack::push(float it) {if(top==size)return false;listArray[top++]=it;return true;}bool Stack::pop(float& it) {if(top==0)return false;it=listArray[--top];return true;}bool Stack::isEmpty() //判断站是否为空{if(top==0)return true;return false;}bool Stack::isOne(){if(top==1)return true;return false;}Stack::~Stack(){delete listArray;}算法的具体步骤用switch语句实现1. 逐一扫描字符串,用ascii码进行判断,如果该字符是数字,则利用x=x*10+str[i]-48将数据由字符类型转换为浮点型数据;2. 如果字符是‘.’,则将‘.’转化为小数点,并将‘.’后的数据转化为小数部分;3. 遇到空格前是数据的,将x押入栈;4. 如果该字符是’+’,’-’,’*’或’/’,判断栈里的元素是否少于两个个,如果少于两个,报错;如果大于等于两个,就弹出两个数据,并进行相应的计算;算法的时空分析因为入栈、出栈的时间复杂度均为Θ(1),所以时间的复杂度主要取决于字符串的长度,空间也同样取决于字符串长度。
C语言实现逆波兰式实例
C语⾔实现逆波兰式实例复制代码代码如下:#include<stdio.h>#include<string.h>typedef struct{char s[20][20];int top;}SQ;void copystr(char *a,char *b){int i=0;do{b[i]=a[i];i++;}while(a[i]!='\0');b[i]='\0';}void voidSQ(SQ *s){s->top=-1;}int ifempty(SQ *s){return(s->top==-1);}void push(SQ *S,char *c){if(S->top==19)printf("over flow\n");else{S->top++;copystr(c,S->s[S->top]);}}char *pop(SQ *S){if(ifempty(S)){printf("over flow!\n");return(NULL);}elsereturn(S->s[S->top--]);}int judge(char *c){if(c[1]=='\0')switch(c[0]){case '+':return(3);case '-':return(3);case '*':return(2);case '/':return(2);default:return(1);}elsereturn(1);}void write(char *a,char *b,char *c){strcat(a,c);strcat(a,b);}int seek(char *c,int start){int signal=1;for(start=start++;c[start]!='\0'&&signal!=0;start++) {if(c[start]==')')signal--;else if(c[start]=='(')signal++;}if(signal==0)return(start-1);else{printf("输⼊⽆效式⼦\n");return(-1);}}void FB(SQ *A,SQ *B){for(;!ifempty(A);){push(B,A->s[A->top]);pop(A);}}char *rewrite(char *A){SQ front;SQ back;int i,j,k,flag=0;char *result;char mid[20];voidSQ(&front);voidSQ(&back);for(i=0;A[i]!='\0';){if(A[i]=='('){j=seek(A,i);for(k=i+1;k<j;k++){mid[k-i-1]=A[k];}mid[j-i-1]='\0';copystr(rewrite(mid),mid);push(&back,mid);i=j+1;}else if(A[i]!='(')mid[0]=A[i];mid[1]='\0';push(&back,mid);i++;}}FB(&back,&front);for(;front.top>=2;){flag=0;for(i=0;i<=front.top;i++){if(judge(front.s[i])==2){flag=1;break;}}if(flag==1){for(;front.top>=2;){if(judge(front.s[front.top])==1&&judge(front.s[front.top-1])==2&&judge(front.s[front.top-2])==1) {write(front.s[front.top],front.s[front.top-1],front.s[front.top-2]);push(&back,front.s[front.top]);pop(&front);pop(&front);pop(&front);}else{push(&back,front.s[front.top]);pop(&front);}}FB(&front,&back);FB(&back,&front);}else{for(;front.top>=2;){if(judge(front.s[front.top])==1&&judge(front.s[front.top-1])==3&&judge(front.s[front.top-2])==1) {write(front.s[front.top],front.s[front.top-1],front.s[front.top-2]);push(&back,front.s[front.top]);pop(&front);pop(&front);pop(&front);}else{push(&back,front.s[front.top]);pop(&front);}}FB(&front,&back);FB(&back,&front);}result=front.s[front.top];return(result);}typedef struct{char c[20];int top;}sq; int execute(char a,char b,char c) {switch(a){case('+'):return((c-48)+(b-48)); case('-'):return((c-48)-(b-48));case('*'):return((c-48)*(b-48));case('/'):return((c-48)/(b-48));}}void voidsq(sq *s){s->top=-1;}int ifsqempty(sq *s){return(s->top==-1);}void pushsq(sq *s,char x){if(s->top==19)printf("over flow!\n");else{s->top=s->top+1;s->c[s->top]=x;}}void popsq(sq *s){if(ifsqempty(s))printf("over flow!\n");elses->top--;}int just(char c){switch(c){case ('+'):return(0);case ('-'):return(0);case ('*'):return(0);case ('/'):return(0);default:return(1);}}void restread(sq *a,sq *b){for(;!ifsqempty(a);){pushsq(b,a->c[a->top]);popsq(a);}}int calculate(char *c){sq rest,read;int i,re;voidsq(&rest);voidsq(&read);for(i=0;c[i]!='\0';i++)pushsq(&read,c[i]);for(;read.top>=2;){for(;read.top>=2;){if(just(read.c[read.top])==0&&just(read.c[read.top-1])==1&&just(read.c[read.top-2]) ==1) {re=execute(read.c[read.top],read.c[read.top-1],read.c[read.top-2]);pushsq(&rest,re+48);popsq(&read);popsq(&read);popsq(&read);}else{pushsq(&rest,read.c[read.top]);popsq(&read);}}restread(&read,&rest);restread(&rest,&read);}return(read.c[0]-48);}void main(){char re[20];char a[20];printf("请输⼊算式:\n");scanf("%s",a);copystr(rewrite(a),re);printf("逆波兰式:\n%s\n",re);printf("求值结果:\n%d\n",calculate(re));}。
逆波兰表达式求值实验报告湖大
HUNAN UNIVERSITY 课程实习报告题目:逆波兰表达式求值学生姓名范舜奕学生学号20100820608专业班级通信6班指导老师吴帆完成日期 2012.04. 07实验二逆波兰表达式求值★问题描述选一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确★基本要求(1)从键盘中输入一个后缀表达式,该表达式包括加减乘除的操作符,一级正整数作为操作数等(2)用堆栈来表示★输入输出格式输入:在字符界面上输入一个后缀表达式,其中两相邻操作数之间利用空格隔开。
以“#”表示结束。
输出:如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字。
如果不正确,请在字符界面上输出表达式错误提示★测试用例输入:2 3 * 1 -#输出:5★设计思路◆为了测试需要,应以浮点数存储输入和输出,利用堆栈来实现算法。
栈的抽象数据类型的定义如下:ADT Stack {数据对象:D={a i| a i∈ElemSet, i=1,2,...,n, n≥0 }数据关系:R={<a i-1 , a i >| a i-1 ,a i∈D, i=2,...,n}基本操作:InitStack(&S)操作结果:构造一个空栈SDestoryStack(&S)初始条件:栈S已存在操作结果:栈S被销毁Pop(&S,e)初始条件:栈S已存在且非空操作结果:删除S的栈顶元素,并用e返回其值Push(&S,e)初始条件:栈S存在且非空操作结果:插入元素e为新的栈顶元素StackLength(&S)初始条件:栈S已存在操作结果:返回S的元素的个数,即栈的长度} ADT LinkLiSt◆本程序包含三个基本模块(1)主程序模块:元素进栈、出栈、删除栈顶元素、实现数字元素的运算(2)线性表模块:实现栈的抽象数据类型(3)元素结构单元模块:定义栈每个元素的结构◆算法的基本思想:定义堆栈的抽象数据类型,读取键盘上输入的数据,根据读取的输入调用入栈函数,判断输入的数据是否合法,通过switch_case结构判断输入运算符的种类,转而执行不同的处理代码。
逆波兰式实验报告
课程实习报告题目:逆波兰表达式班级:智能1201班姓名:易全政学号:201208070123完成日期:2014.3.27一、需求分析1、本程序要求输入一个包含四则运算且操作数为正数的逆波兰表达式,并利用堆栈求出结果值2、输入的的后缀表达式由键盘输入到字符界面,并要求相邻的操作数之间用空格隔开,最后以‘#’字符作为结束标识符3、如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字,如果不正确,请在字符界面上输出表达式错误提示4、测试数据输入2 3 * 1 -#输出5二、概要设计1、抽象数据类型为实现上述程序的功能,应该以字符串存入输入的字符以及操作数为实现操作数的保存以及运算,应该利用堆栈来完成2、算法的基本思想通过键盘一些字符与操作数,利用一个字符串来保存,并同时定义一个栈与字符串指针,每次栈里面保存当前输入的操作数,而当遇到运算符时将栈顶与栈的上个元素进行相应的运算,并将栈顶元素弹出同时保存进入新的栈顶中,在最后进行判断从而实现对输入正确的逆波兰表达式输出其运算结果。
3、程序的流程程序的流程由三个模块组成:(1)输入模块:输入字符串,并将地址赋给字符串指针(2)运算模块:输入字符的判断,操作数的入栈以及相应的运算(3)输出模块:对于符合条件的逆波兰表达式输出运算结果三、详细设计1、物理数据类型题目要求输入一行运算表达式,为一个字符串,并定义字符串指针保存其地址;定义一个顺序栈,用double型数组来保存栈内元素;用typedef定义一个新的结构体类型;含有很多的int与double型的变量;23、算法的时空分析根据程序的实现情况可知,算法运行时间主要集中在do while循环上,所以对于该字符串,若含有n个字符,则必有产生的时间代价为:Θ(n);4、输入输出的格式输入请输入要计算的表达式://提示等待输入输出等待输出输出的式子的构成为:输入的表达式= 运算结果或者输入的表达式--- error四、测试结果第一组测试:单字符减加乘除:输入2 3 4 + - 5 * 3 /#输出2 3 4 + - 5 * 3 /# =-8.33第二组测试:连续字符的加减乘除输入12 34 + 234 – 2 * 3 /#输出12 34 + 234 – 2 * 3 /# =-125.33第三组测试:输入错误情况测试输入1 2 3 -#输出1 2 3 -#———Input error!第四组测试:计算错误情况测试输入3 0 /#输出3 0 /#———Input error!五、实验心得本次实验通过在栈的基础上要进行对逆波兰表达式的计算,最初只是进行了单个字符的计算,并且很容易的就编出来了并且验证争取,但是在处理连续字符,例如12 2 *# 上却多次尝试但是都没有效果,就是在用cin输入字符串时,遇到空格键会自动终止,但是运算结果不正确,因为在同学的提示下利用getline来输入字符串就可以避免这种情况,因为我在原有程序的基础上做出了改进,并实现了最后的编程。
(编译原理)逆波兰式算法的源代码
一.实验目的1.深入理解算符优先分析法2.掌握FirstVt和LastVt集合的求法有算符优先关系表的求法3.掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化二.实验内容及要求将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。
程序输入/输出示例:输出的格式如下:(1)(2)输入一以#结束的中缀表达式(包括+—*/()数字#)(3)(4)逆波兰式备注:(1)在生成的逆波兰式中如果两个数相连则用&分隔,如28和68,中间用&分隔;注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、数字,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。
同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;三.实验过程1、逆波兰式定义将运算对象写在前面,而把运算符号写在后面。
用这种表示法表示的表达式也称做后缀式。
逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。
采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。
2、产生逆波兰式的前提中缀算术表达式3、逆波兰式生成的实验设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。
逆波兰实验报告
实验一约瑟夫环问题基本要求需要基于线性表的基本操作来实现约瑟夫问题需要利用数组来实现线性表输入输出格式输入格式:n,m输出格式1:在字符界面上输出这n个数的输出序列输出格式2:将这n个数的输出序列写入到文件中实验原理设编号为1-n的n(n>0)个人按顺时针方向围成一圈.首先第1个人从1开始顺时针报数.报m的人(m 为正整数).令其出列。
然后再从他的下一个人开始,重新从1顺时针报数,报m的人,再令其出列。
如此下去,直到圈中所有人出列为止。
求出列编号序列。
利用数组对每个人排序。
利用while函数找到数到m的人,当第L个人出圈之后,报数,并在用后面的人依次填充。
实验程序#include<iostream>using namespace std;int main(){int A[100],n,m;cout<<"输入总人数和喊到的数字:\n";cin>>n>>m;int i,j,k=n;for(i=0;i<n;i++)A[i]=i+1; //让数组的值从1开始while(k>0){for(j=1;j<m;j++)i=(i+1)%k; //寻找第一个喊到m的人cout<<A[i]<<" ";for(j=i+1;j<k;j++) //从i+1开始继续向后喊数A[j-1]=A[j];k--; //剩余人数}cout<<"\n"<<A[i];cout<<endl;return 0;}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
bool isEmpty();//判断栈是否为空
bool isOne(); //判断栈里是否只有且仅有一个元素
};
成员函数的函数体
Stack::Stack(int sz) //栈构造函数
{
size=sz;
top=0;
listArray=new float[size];
class Stack
{
private:
int size;
int top;
float *listArray;
public:
Stack(int sz=20);
~Stack();
bool push(float it);//入栈
bool pop(float& it);//出栈
bool isEmpty();//判断栈是否为空
4.如果该字符是’+’,’-’,’*’或’/’,判断栈里的元素是否少于两个个,如果少于两个,报错;如果大于等于两个,就弹出两个数据,并进行相应的计算;
算法的时空分析
因为入栈、出栈的时间复杂度均为Θ(1),所以时间的复杂度主要取决于字符串的长度,空间也同样取决于字符串长度。时间复杂度为Θ(n)。
输入和输出的格式
2.如果字符是‘.’,则将‘.’转化为小数点,并将‘.’后的数据转化为小数部分;
3.遇到空格前是数据的,将x押入栈;
4.如果该字符是’+’,’-’,’*’或’/’,判断栈里的元素是否少于两个个,如果少于两个,报错;如果大于等于两个,就弹出两个数据,并进行相应的计算;
程序的流程
输入字符串,程序对字符串依次扫描。扫描一位,处理一位。扫描完成后,判断栈里是不是只有一个数据,若是,得到正确结果;若不是,则表达式出错。
float *listArray;//存储浮点型数字的数组
成员函数:
bool push(float it);
bool pop(float& it);
bool isEmpty();//判断栈为空
bool isOne();//判断栈是否只有一个元素
算法的基本思想
1.逐一扫描字符串,用ascii码进行判断,如果该字符是数字,则利用x=x*10+str[i]-48将数据由字符类型转换为浮点型数据;
return true;
return false;
}
bool Stack::isOne()
{
if(top==1)
return true;
return false;
}
Stack::~Stack()
{
delete listArray;
}
//此函数传进输入的字符串,并对字符串进//行扫描并进行相应处理,得到结果(函数声//明)
逆波兰表达式求值
一、需求分析
1、从键盘中输入一个后缀表达式,该表示包括加减乘除等操作符,以及正整数作为操作数等。
2、用堆栈来实现
3、测试数据
输入:2 3 * 1 –#
输出:2 3 * 1 -- =5
二、概要设计
抽象数据类型
需要一个浮点数栈来存储还没有计算的浮点数或者运算的结果。
ADTStack
数据成员:int size; int top;//分别用于存储栈大小、栈顶位置
{
Stack aStack;
float x=0,y=0,s1,s2,temp;
bool isOne();//判断栈里是否一个元素
};
Stack::Stack(int sz) //栈构造函数
{
size=sz;
top=0;
listArray=new float[size];
}
bool Stack::push(float it)
{
if(top==size)
return false;
输入:2 3 * 1 –#
输出:2 3 * 1 -- =5
五、测试结果
六、用户使用说明(可选)
1.运行程序后,直接输入后缀表达式;
2.用户输入的表达式必须符合后缀表达式的要求,并以‘#’号结束。
七、附录(可选)
#include <iostream>
#include <string>
using namespace std;
listArray[top++]=it;
return true;
}
bool Stack::pop(float& it)
{
if(top==0)
return false;
it=listArray[--top];
return true;
}
bool Stack::isEmpty() //判断站是否为空
{
if(top==0)
}
bool Stack::push(float it)
{
if(top==size)
return false;
listArray[top++]=it;
return true;
}
bool Stack::pop(float& it)
{
if(top==0)
return false;
it=listArray[--top];
三、详细设计
物理数据类型
用浮点数类型的栈存储运算中要用的数据,需要入栈、出栈,故设计如下的浮点类型的栈:
class Stack
{
private:
int size;
int top;
float *listArray;
public:
Stack(int sz=20);
~Stack();
bool push(float it);//入栈
return true;
}
bool Stack::isEmpty() //判断站是否为空
{
if(top==0)
return true;
return false;
}
bool Stack::isOne()
{
if(top==1)
return true;
return false;
}
Stack::~Stack()
void compute(char* str);
int main()
{
char str[20];
cin.getline(str,20,'#');
compute(str);
return 0;
}
//此函数传进输入的字符串,并对字符串进//行扫描并进行相应处理,得到结果(函数体)
void compute(char* str)
{
delete listArray;
}
Hale Waihona Puke 算法的具体步骤用switch语句实现
1.逐一扫描字符串,用ascii码进行判断,如果该字符是数字,则利用x=x*10+str[i]-48将数据由字符类型转换为浮点型数据;
2.如果字符是‘.’,则将‘.’转化为小数点,并将‘.’后的数据转化为小数部分;
3.遇到空格前是数据的,将x押入栈;