用栈和二叉树实现中缀表达式转后缀表达式构建计算机并求值实验报告

合集下载

中缀表达式转后缀表达式---栈--二叉树---四则运算

中缀表达式转后缀表达式---栈--二叉树---四则运算

中缀表达式转后缀表达式---栈--⼆叉树---四则运算 我们平常书写的四则运算表达式属于中缀表达式,形式为"9+(3-1)*3+10/2",因为所有的运算符号都在两操作数之间,所以称为中缀表达式。

我们使⽤中缀表达式来计算表达式的值,不过这种形式并不适合计算机求解。

接下来,我们将中缀表达式转化为后缀表达式,所谓的后缀表达式就是操作符位于操作数后⾯的不包含括号的算数表达式,也叫做逆波兰表达式。

1)⾸先介绍⼀种⼈⼯的转化⽅法()。

以"9+(3-1)*3+10/2"为例,按照运算的规则,找出⾸先计算的部分,这部分包含两个操作数和⼀个操作符,将操作符移动到两个操作数右侧,这就完成了第⼀部分的转换,将这部分看作⼀个操作数,按照运算规则,以相同的⽅法转换,转换过程如下:2)还可以利⽤⼆叉树求得后缀表达式,⾸先利⽤中缀表达式构造⼆叉树,数字是叶⼦节点,操作符为根节点。

每次找到“最后计算”的运算符,作为当前根节点,运算符左侧表达式作为左节点,右侧表达式作为右节点,然后递归处理()。

9+(3-1)*3+10/2对应的⼆叉树的构造过程如下图所⽰: 此⼆叉树做后序遍历就得到了后缀表达式。

对应代码:3)还可以利⽤栈来实现中缀表达式转化为后缀表达式。

转化⽅法如下所述:a.从左向右扫描表达式,如果是数字就输出,否则转b。

b.如果当前扫描的字符是")",则栈顶元素出栈并输出⼀直到栈顶元素为"(",然后删除栈顶元素"(",并不输出。

c.如果扫描的字符或者栈顶元素是“(”,扫描的字符直接⼊栈。

即使扫描的字符是")"也不会⼊栈,因为如果是")",会出栈⾄栈顶元素是"("。

d.如果扫描字符是"+"或者"-",则⼀直出栈⾄栈顶元素为"+"或者"-"或者"("。

C语言实现一.二叉树操作 二.用栈实现算术表达式求值 课设报告

C语言实现一.二叉树操作 二.用栈实现算术表达式求值  课设报告
沈阳理工大学
沈阳理工大学课程设计专用纸
No. 1
题目 一.二叉树操作(1)二.算术表达式求
一、课程设计的目的
本学期我们对《数据结构》这门课程进行了学习。这门课程是一门实践性非常强的 课程,为了让大家更好地理解与运用所学知识,提高动手能力,我们进行了此次课程设 计实习。这次课程设计不但要求学生掌握《数据结构》中的各方面知识,还要求学生具 备一定的 C 语言基础和编程能力。
{ int k; char *temp; if(len<=0) { *T=NULL;
沈阳理工大学
沈阳理工大学课程设计专用纸
No. 5
return; } *T=(BitNode*)malloc(sizeof(BitNode)); (*T)->data=*pre; for(temp=in;temp<in+len;temp++)
int h,lh,rh; if(T==NULL)
h=0; else {
lh=Depth(T->lchild); rh=Depth(T->rchild); if(lh>=rh)
h=lh+1; else
h=rh+1; } return h; }
沈阳理工大学
沈阳理工大学课程设计专用纸
No. 6
4、运行结果 先输入一棵树的先序遍历序列和中序遍历序列,然后构造出这颗二叉树,并输
(2)题目二的内容和要求: 1、算术表达式由操作数、运算符和界限符组成。操作数是正整数,运算符为 加减乘除,界限符有左右括号和表达式起始 2、将一个表达式的中缀形式转化为相应的后缀形式 3、依据后缀表达式计算表达式的值
沈阳理工大学
沈阳理工大学课程设计专用纸

实验五 二叉树的应用----表达式求值

实验五  二叉树的应用----表达式求值

浙江大学城市学院实验报告课程名称python高级程序设计实验项目名称实验五二叉树的应用----表达式求值实验成绩指导老师(签名)日期一.实验目的和要求1、掌握二叉树的链式存储结构;2、掌握在二叉链表上的二叉树的基本操作;3、掌握二叉树的简单应用----表达式树的操作。

二.实验内容1、在实验四中,已经实现了对一个中缀表达式可以用栈转换成后缀表达式,并可对后缀表达式进行求值计算的方法。

另一种思路是可以利用二叉树建立表达式树,通过对该表达式树进行求值计算,本实验实现:输入一个中缀表达式,建立该表达式的二叉树,然后对该二叉树进行表达式值的计算。

如一个中缀达式(6+2)*5 的二叉树表示为如下所示时,该二叉树的后序遍历62+5*正好就是后缀表达式。

设一般数学表达式的运算符包括+、-、*、/ 四种,当然允许(),且()优先级高。

为方便实现,设定输入的表达式只允许个位整数。

要求设计一个完整的程序,对输入的一个日常的中缀表达式,实现以下功能:⏹建立对应的二叉树⏹输出该二叉树的前序序列、中序序列、后序序列⏹求该二叉树的高度⏹求该二叉树的结点总数⏹求该二叉树的叶子结点数⏹计算该二叉树的表达式值分析:(1)表达式树的构建方法:●构建表达式树的方法之一:直接根据输入的中缀表达式构建对于任意一个算术中缀表达式,都可用二叉树来表示。

表达式对应的二叉树创建后,利用二叉树的遍历等操作,很容易实现二叉树的求值运算。

因此问题的关键就是如何创建表达式树。

对于一个中缀表达式来说,其表达式对应的表达式树中叶子结点均为操作数,分支结点均为运算符。

由于创建的表达式树需要准确的表达运算次序,因此,在扫描表达式创建表达式树的过程中,当遇到运算符时不能直接创建结点,而应将其与前面的运算符进行优先级比较,根据比较结果进行处理。

这种处理方式在实验四中以采用过,可以借助一个运算符栈,来暂存已经扫描到的还未处理的运算符。

根据表达式树与表达式对应关系的递归定义,每两个操作数和一个运算符就可以建立一棵表达式二叉树,而该二叉树又可以作为另一个运算符结点的一棵子树。

中缀转后缀表达式计算报告

中缀转后缀表达式计算报告

目录一、设计思想 (01)二、算法流程图 (02)三、源代码 (04)四、运行结果 (14)五、遇到的问题及解决 (16)六、心得体会 (16)一、设计思想(1)中缀表达式转后缀表达式并计算创建一个数组存储输入的计算表达式。

另创建一个数组储存将要生成的后缀表达式。

创建一个栈储存操作符。

对已存储的表达式数组扫描。

判断当前节点,如果是操作数或’.’,直接加入后缀表达式中,如果是操作符,则比较前一个操作符与当前操作符的优先级。

如果前一个操作符的优先级较高,则将前一个操作符加入后缀表达式中,否则将操作符压入操作符栈。

如果遇到左括号’(’,直接入栈;如果遇到右括号’)’,则在操作符栈中反向搜索,直到遇到匹配的左括号为止,将中间的操作符依次加到后缀表达式中。

当执行完以上操作,发现栈中仍有剩余操作符,则将操作符依次加到后缀表达式中。

此时中缀表达式已经转换成了后缀表达式。

对后缀表达式进行计算。

如果后缀表达式为大于0小于9的字符,则将它转换成浮点型数据并存入数栈中。

如果遇到操作符,则从数栈中提取两个数,进行相应的运算。

依次进行下去,当没有运算符是,运算结束得到最后的结果。

(2)直接表达式求值创建一个数组存储输入的计算表达式。

创建两个栈,一个字符型的栈,一个双精度型的栈。

分别用来存储字符和数。

对已存储的表达式数组扫描。

判断当前节点,如果是操作数和’.’,将字符型的操作数转换为浮点型的数后存入操作数栈。

如果是操作符则判断操作符的优先级。

如果字符栈中已存储符号的优先级小于要存入的字符的优先级,则直接让字符入操作符栈。

如果字符栈中已存储符号的优先级大于或等于要存入的字符的优先级,则取出操作符栈中的一个字符和操作数栈中的两个数进行计算,然后将结果存入操作数栈中,同上进行下去,直到字符栈中已存储符号的优先级小于要存入的字符的优先级时,将操作符存入操作符栈中。

当遇到左括号’(’,将左括号直接存入操作符栈中。

当遇到右括号’)’,则在操作符栈中反向搜索,并且每搜到一个字符就在操作数栈中取两个数进行相应的计算。

中缀表达式转后缀表达式报告

中缀表达式转后缀表达式报告

目录1. 课题分析 (1)1.1设计目的 (1)1.2主要内容 (1)1.2.1中缀表达式转换为后缀表达式 (1)1.2.2后缀表达式求值 (1)1.3设计要求 (2)2.总体设计 (2)2.1数据类型的定义 (2)2.2主程序的流程 (3)3.详细设计(源代码) (4)4.调试分析 (4)4.1问题1 (8)4.2问题2 (8)4.3问题3 (9)5.测试结果 (9)6.心得体会 (10)7.参考文献 (10)1.课题分析1.1设计目的(1)掌握栈“后进先出”的特点。

(2)掌握栈的典型应用——中缀表达式转后缀表达式,并利用后缀表达式求值。

(3)掌握串或者数组的相关操作。

1.2主要内容1.2.1中缀表达式转换为后缀表达式(1)定义一个运算符栈,并输入一个中缀表达式(运算对象存在多位整数,运算符为+、-、*、/、%及括号),然后从中缀表达式中自左至右依次读入各个字符。

(2)如果是第一次读入运算对象,也是直接输出到后缀表达式;如果不是第一次读入运算对象,并且前一个读入的字符是运算对象,也是直接输出到后缀表达式;如果不是第一次读入运算对象,并且前一个读入的字符是运算符,则先输出逗号作为分隔符,然后再将该运算对象输出到后缀表达式。

(3)如果读入的是运算符,并且运算符栈为空,则将该运算符直接进栈;如果栈不为空,则比较该运算符和栈顶运算符的优先级。

若该运算符高于栈顶运算符的优先级,则将该运算符直接进栈;若该运算符低于或等于栈顶运算符的优先级,则将栈中高于或等于该运算符优先级的元素依次出栈,然后再将该运算符进栈。

每出栈一个运算符时,先输出一个逗号到后缀表达式作为分隔符,然后再将出栈运算符输出到后缀表达式。

(4)如果读入的是开括号“(”,则直接进栈;如果读入的是闭括号“)”,则一直出栈并输出到后缀表达式,知道遇到一个开括号“(”为止。

开括号“(”和闭括号“)”均不输出到后缀表达式。

(5)重复②、③、④步,知道中缀表达式结束,然后将栈中剩余的所有运算符依次出栈。

2022年北工大数据结构第二次上机中缀转后缀实验报告

2022年北工大数据结构第二次上机中缀转后缀实验报告

北京工业大学- 第学期信息学部计算机学院3月31日报告题目:输入中缀体现式,输出后缀体现式,并对体现式求值A.分析中缀体现式旳运算顺序受运算符优先级和括号旳影响。

因此,将中缀体现式转换成等价旳后缀体现式旳核心在于如何恰当旳去掉中缀体现式中旳括号,然后在必要时按照先乘除后加减旳优先规则调换运算符旳先后顺序。

在去括号旳过程中用栈来储存有关旳元素。

基本思路:从左至右顺序扫描中缀体现式,用栈来寄存体现式中旳操作数,开括号,以及在这个开括号背面旳其她临时不能拟定计算顺序旳内容。

(1)当输入旳是操作数时,直接输出到后缀体现式(2)当遇到开括号时,将其入栈(3)当输入遇到闭括号时,先判断栈与否为空,若为空,则表达括号不匹配,应作为错误异常解决,清栈退出。

若非空,则把栈中元素依次弹出,直到遇到第一种开括号为止,将弹出旳元素输出到后缀体现式序列中。

由于后缀体现式不需要括号,因此弹出旳括号不放到输出序列中,若没有遇到开括号,阐明括号不匹配,做异常解决,清栈退出。

(4)当输入为运算符时(四则运算+ - * / 之一)时:a.循环,当(栈非空&&栈顶不是开括号&&栈顶运算符旳优先级不低于输入旳运算符旳优先级)时,反复操作将栈顶元素弹出,放到后缀体现式中。

b.将输入旳运算符压入栈中。

(5)最后,当中缀体现式旳符号所有扫描完毕时,若栈内仍有元素,则将其所有依次弹出,放在后缀体现式序列旳尾部。

若在弹出旳元素中遇到开括号,则阐明括号不匹配,做异常解决,清栈退出。

B.实现#include<stdio.h>#include<string.h>#include<stdlib.h>#include<stack>using namespace std;#define N 1000char infix[N]; //中缀体现式(未分离,都在一种字符串里)char expression[N][10]; //保存预解决过旳体现式,也就是每个元素都分离过旳体现式char suffix[N][10]; //保存后缀体现式旳操作数int count;//体现式中元素旳个数(一种完整到数字(也许不止一位数)或者符号)int suffixLength;//后缀体现式旳长度int level(char a){switch(a){case '#':return 0;case '+':case '-':return 1;case '*':case '/':return 2;case '^':return 3;default:break;}return -1;}int isDigital(char x){if( (x>='0'&&x<='9') || (x>='A'&&x<='Z') || (x>='a'&&x<='z') || (x=='.') )return 1;return 0;}int isNumber(char *str){int i;for(i=0;str[i];i++){if(isDigital(str[i])==0)return 0;}return 1;}/*************************************预解决中缀体现式,把持续旳字符分离成不同旳元素,用字符串数组(expression[][])保存,以便背面旳计算,由于这里考虑了运算数也许不全是个位数例如:(12+3)在解决成后缀体现式时,是123+,容易产生歧义(1+23 ? 12+3)*************************************/void pretreatment(char *str){int i,j,numberFlag;char temp[3];char number[10];count=0;numberFlag=0;for(j=0,i=0;str[i];i++){if(isDigital(str[i])==0){if(numberFlag==1){number[j]=0;strcpy(expression[count++],number); j=0;numberFlag=0;}if(str[i]!=' '){temp[0]=str[i];temp[1]=0;strcpy(expression[count++],temp); }}else {numberFlag=1;number[j++]=str[i];}}puts("分离后旳体现式为");for(i=0;i<count;i++){printf("%s ",expression[i]);}puts("");puts("");}/*****************************************中缀体现式转后缀体现式遍历字符串,对于str[i]str[i]是运算数(或者是字母替代旳运算变量)输出;str[i]是符号,有两种状况(1),是右括号,栈顶元素输出,直到与str[i]匹配旳左括号出栈(左括号不用输出打印)(2),是运算符,判断str[i]与栈顶元素旳优先级,str[i]优先级不高于栈顶符号,则栈顶元素输出,直到栈空或者栈顶符号优先级低于str[i]*****************************************/void infix_to_suffix(char str[N][10]){memset(suffix,0,sizeof(suffix));suffixLength=0;stack <char*> st;int i=0;char Mark[2]="#";st.push(Mark);do{if(isNumber(str[i])==1)//运算数直接保存到后缀体现式中strcpy(suffix[suffixLength++],str[i]);else if(str[i][0]=='(') //是左括号,直接入栈st.push(str[i]);else if(str[i][0]==')'){ //是右括号,栈顶出栈,直到与其匹配旳左括号出栈while( strcmp(st.top(),"(")!=0 ){char temp[10];strcpy(temp,st.top());strcpy(suffix[suffixLength++],temp);st.pop();}st.pop();}else if( strcmp(st.top(),"(")==0 )//是运算符,且栈顶是左括号,则该运算符直接入栈st.push(str[i]);else { //是运算符,且栈顶元素优先级不不不小于运算符,则栈顶元素始终//出栈,直到栈空或者遇到一种优先级低于该运算符旳元素while( !st.empty() ){char temp[10];strcpy(temp,st.top());if( level(str[i][0]) > level(temp[0]) )break;strcpy(suffix[suffixLength++],temp);st.pop();}st.push(str[i]);}i++;}while(str[i][0]!=0);while( strcmp(st.top(),"#")!=0 ){ //将栈取空结束char temp[10];strcpy(temp,st.top());strcpy(suffix[suffixLength++],temp);st.pop();}puts("后缀体现式为:");for(i=0;i<suffixLength;i++){printf("%s",suffix[i]);}puts("");puts("");}/**************************************计算后缀体现式旳值**************************************/char kt[N][10];int stackTop;void getResult(char str[N][10]){stackTop=0;/*这里要注意,内存旳分派方案导致 i 旳位置就在temp[9]旁边,然后strcpy()函数直接拷贝内存旳话,在temp越界状况下会覆盖 i 旳值*/int i;char temp[10];for(i=0;i<suffixLength;i++){if(isNumber(str[i])==1){strcpy(kt[stackTop++],str[i]);}else {char a[10],b[10];double na,nb,nc;strcpy(a,kt[stackTop-1]);na = atof(a);stackTop--;strcpy(b,kt[stackTop-1]);nb = atof(b);stackTop--;if(str[i][0]=='+')nc=nb+na;else if(str[i][0]=='-')nc=nb-na;else if(str[i][0]=='*')nc=nb*na;else if(str[i][0]=='/')nc=nb/na;sprintf(temp,"%lf",nc);strcpy(kt[stackTop++],temp);}}puts("\nThe result is : %f\n");printf("%s\n",kt[stackTop-1]);}int main(){printf("Please input calculate Expression :\n"); char temp[N];while(gets(infix)){strcpy(temp,infix);pretreatment( strcat(temp," ") );infix_to_suffix(expression);getResult(suffix);}return 0;}C.总结实验需要细心细心再细心。

数据结构表达式求值实验报告-无删减范文

数据结构表达式求值实验报告-无删减范文

数据结构表达式求值实验报告数据结构表达式求值实验报告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位整数)转换为后缀式,然后计算该表达式

利用栈或二叉树将算术表达式输入串(只要求1位整数)转换为后缀式,然后计算该表达式

利用栈或二叉树将算术表达式输入串(只要求1位整数)转换为后缀式,然后计算该表达式利用栈或二叉树将算术表达式输入串(只要求1位整数)转换为后缀式,然后计算该表达式算术表达式的计算通常需要将中缀表达式转换为后缀表达式,然后使用栈或二叉树对后缀表达式进行计算。

首先,我们需要定义运算符的优先级。

在本例中,我们只考虑加法'+'和减法'-'两个运算符,其中加法的优先级较低。

接下来,我们可以使用栈来转换中缀表达式为后缀表达式。

具体步骤如下:1. 创建一个空栈和一个空字符串,用于存储后缀表达式。

2. 从左到右遍历中缀表达式的每个字符。

3. 对于每个字符,进行如下处理:- 如果是数字,则直接添加到后缀表达式字符串中。

- 如果是运算符,则比较其与栈顶运算符的优先级。

- 如果栈为空或栈顶运算符为'(',则直接将当前运算符入栈。

- 如果当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符入栈。

- 如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符弹出并加入后缀表达式字符串中,直到栈为空或栈顶运算符为'(',然后将当前运算符入栈。

- 如果是左括号'(',则直接将其入栈。

- 如果是右括号')',则将栈顶运算符弹出并加入后缀表达式字符串中,直到遇到左括号'(',然后将左括号出栈但不加入后缀表达式字符串。

4. 遍历完中缀表达式后,将栈中剩余的运算符依次弹出并加入后缀表达式字符串中。

现在,我们已经将中缀表达式转换为后缀表达式。

接下来,我们可以使用栈或二叉树来计算后缀表达式。

1. 创建一个空栈,用于存储操作数。

2. 从左到右遍历后缀表达式的每个字符。

3. 对于每个字符,进行如下处理:- 如果是数字,则将其转换为整数并入栈。

- 如果是运算符,则从栈中弹出两个操作数,进行相应的运算,并将结果入栈。

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

中缀表达式改为后缀表达式(实验报告附C++源码-二叉树)

中缀表达式改为后缀表达式(实验报告附C++源码-二叉树)

中缀表达式改后缀表达式一、需求分析1.本程序采用的是二叉树后序遍历来实现四则运算的中缀表达式改为后缀表达式;2.需要用一个类来代表数据的结构;3.输入输出格式:输入:在字符界面上输入一个中缀表达式,回车表示结束。

输出:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。

二、概要设计ﻩ抽象数据类型用Node类来定义一个结点:classNode{public:ﻩchar ch[max];//每个结点的字符串Node* lChild;//左指针Node*rChild;//右指针Node();~Node();};算法的基本思想1.输入中缀表达式,用函数对字符串中的空格或者等号进行处理,由于程序需要,会在输入的字符串结尾加入‘=’;2.用函数一次扫描每一个字符,有异常字符,报错;没有,则每次取出连续的数字字符或加减乘除的符号,放入结点,并按规则,将上一结点的左或右指针指向该结点;2.扫描:①扫描过程在树的建立过程中;②每次扫描,获得数字字符作为一个结点,并返回数字字符后的算数运算符或者括号;③根据返回的运算符或括号,确定相应的指针赋值或是新建结点;(有错时,会退出程序)3.后序遍历法输出获得结果。

算法的时空分析因为在处理字符串时,需要逐一扫描,也建立了新的字符数组,所以时间复杂度为Θ(n);同样,扫描的循环,也与字符串的长度有关,时间复杂度也为Θ(n)输入和输出的格式ﻩ输入:3.4+5*(2*(4+5)+7)输出:3.4 5 24 5 + * 7 +* +五、测试结果六、实验总结这个程序好难,自己很难想到这方法。

不过,没想法时,看不懂别人的程序时,可以通过调试的方法,去获取程序的主要思想,从而变为自己的想法,去实现他。

代码嘛,主要是多写,多仿,写代码的能力自然而然就提高了。

七、附录(可选)#include<iostream>#include<string>using namespace std;constintmax=100;class Node{public:charch[max];Node* lChild;Node* rChild;ﻩNode();ﻩ~Node();};Node::Node(){strcpy(ch,"");ﻩlChild=rChild=NULL;}Node::~Node(){if(lChild!=NULL)ﻩﻩdelete lChild;if(rChild!=NULL)ﻩﻩdelete rChild;}static int count=0;staticchar array[max];//保存原始的中缀表达式static char str[2*max];//保存后序遍历出来的字符串,为表达式求值提供方便staticint k=0;voidenter();//输入函数char getOp(Node *temp);//temp指针保存每个接点的,返回的是运算符或者Node* crtTree(Node* root); //传入根结点指针,返回根结点指针voidoutput(Node *root);//获得处理后的字符串bool isError(char);//判断字符是否有问题void deal();//对字符数组进行处理int main(){ﻩNode* root=NULL;cin.getline(array,40);deal();root=crtTree(root);ﻩoutput(root);ﻩcout << str;return0;}char getOp(Node *temp)//将数字字符存入一//个结点,并返回数字字符的后一个符号{int i=0;if(isError(array[count]))ﻩ{ﻩﻩexit(0);ﻩ}ﻩwhile(array[count]<='9'&&array[count]>='0'||array[count]=='.'){ﻩﻩtemp->ch[i]=array[count];ﻩi++;count++;}ﻩtemp->ch[i]='\0';count++;ﻩreturn array[count-1];}Node* crtTree(Node* root){Node *p,*q;char op;ﻩif(root==NULL){ﻩroot=newNode;ﻩp=new Node;}ﻩop=getOp(root);ﻩwhile(op!='=')ﻩ{ﻩq=newNode;ﻩq->ch[0]=op;ﻩq->ch[1]='\0';ﻩswitch(op)ﻩﻩ{ﻩﻩcase '+':ﻩcase '-': q->lChild=root;ﻩﻩroot=q;ﻩﻩp=newNode;ﻩﻩﻩop=getOp(p);ﻩﻩﻩﻩﻩroot->rChild=p;ﻩﻩbreak;ﻩﻩcase '*':ﻩcase '/':if(root->ch[0]=='+'||root->ch[0]=='-')ﻩﻩﻩﻩ{ﻩﻩﻩﻩp=new Node;ﻩstrcpy(p->ch,root->ch);ﻩﻩﻩp->lChild=root;ﻩﻩﻩﻩp->rChild=q;ﻩﻩﻩop=getOp(root);ﻩﻩﻩﻩroot=p;ﻩﻩﻩ }ﻩelseﻩﻩﻩ{ﻩq->lChild=root;ﻩﻩﻩroot=q;ﻩﻩﻩp=new Node;ﻩﻩﻩop=getOp(p);ﻩﻩroot->rChild=p;ﻩﻩﻩﻩ}ﻩﻩbreak;ﻩcase '(':p=root;ﻩﻩﻩwhile(p->rChild)ﻩﻩﻩp=p->rChild;ﻩﻩif(p->lChild==NULL)ﻩ{ﻩﻩﻩﻩp->lChild=crtTree(p->lChild);//递归创建//括号里的指针ﻩop=array[count];ﻩﻩcount++;ﻩﻩﻩbreak;ﻩﻩﻩ}ﻩelseﻩﻩﻩﻩ{ﻩﻩﻩﻩp->rChild=crtTree(p->rChild);//递归创//建括号里的指针ﻩﻩﻩﻩop=array[count];ﻩﻩﻩcount++;ﻩﻩﻩﻩbreak;ﻩﻩ}ﻩcase ')':returnroot;}}ﻩreturn root;}void output(Node*root) //传入根结点,后//序遍历历赋值给另一个字符数组(主要是//为了给后序的计算表达式值提供方便){ﻩint n;ﻩif(root)ﻩ{ﻩﻩoutput(root->lChild);ﻩoutput(root->rChild);ﻩﻩn=0;ﻩwhile(root->ch[n]!='\0')ﻩstr[k++]=root->ch[n++];str[k++]=' ';ﻩ}}bool isError(char ch) //判断每个字符//是否有错{ﻩif(ch!='+'&&ch!='-'&&ch!='*'&&ch!='/'&&!(ch<='9'&&ch>='0')&&ch!='.'&&ch!='('&&ch!=')'){ﻩcout << "字符错误!";ﻩreturn true;}return false;}void deal() //对字符数组进行处理{ﻩint i=0,n=0;ﻩwhile(array[i])ﻩ{ﻩif(array[i]==''||array[i]=='=') ﻩﻩi++;ﻩﻩarray[n++]=array[i++];ﻩ}array[n++]='=';array[n]='\0';}--。

中缀表达式转后缀表达式实验报告

中缀表达式转后缀表达式实验报告

实验题目:中缀表达式转后缀表达式实验报告一、实验目的本实验旨在通过编写程序,掌握中缀表达式转后缀表达式的算法,并进行实际的转换操作,加深对中缀表达式和后缀表达式的理解,提高编程能力。

二、实验原理1. 中缀表达式:中缀表达式是我们平常常见的算术表达式,如 a + b * c。

2. 后缀表达式(逆波兰表达式):后缀表达式是没有括号,而操作符号放在两个操作数之后的表达式,如 a b c * +。

中缀表达式转后缀表达式的算法步骤如下:- 从左到右遍历中缀表达式的每个数字和操作符;- 如果是数字,则直接输出到后缀表达式;- 如果是操作符,则将其与栈顶元素进行比较,如果比栈顶元素的优先级高或相等,则将栈顶元素弹出,输出到后缀表达式中,直到栈顶元素优先级低于该操作符,然后将该操作符压入栈中;- 遍历完中缀表达式后,将栈中的操作符依次弹出,输出到后缀表达式中。

三、实验过程1. 设计程序我们设计了一个简单的算法,实现中缀表达式转后缀表达式的功能。

我们采用了栈的数据结构来辅助转换过程,具体实现如下:```pythonclass InfixToPostfix:def __init__(self):self.stack = []self.output = []def is_higher_precedence(self, op1, op2):precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}return precedence[op1] >= precedence[op2]def convert(self, infix):for char in infix:if char.isalnum():self.output.append(char)elif char in '+-*/^':while self.stack andself.is_higher_precedence(self.stack[-1], char):self.output.append(self.stack.pop())self.stack.append(char)while self.stack:self.output.append(self.stack.pop())return ''.join(self.output)```2. 编写测试用例为了验证程序的正确性,我们编写了一系列的测试用例,包括简单的表达式(如 a+b*c)、带括号的表达式(如 (a+b)*c)、带有多位数的表达式(如 12+34*56)等多种情况。

中缀求值实验报告

中缀求值实验报告

一、实验目的1. 理解中缀表达式及其求值原理。

2. 掌握中缀表达式的转换方法,即将中缀表达式转换为后缀表达式。

3. 实现中缀表达式的求值算法,并编写相应的程序。

二、实验原理中缀表达式是一种常见的数学表达式表示方式,其特点是运算符位于操作数之间。

例如,表达式 "3 + 4 2" 就是一个中缀表达式。

中缀表达式转换为后缀表达式(也称为逆波兰表达式)是求值的关键步骤,因为后缀表达式可以直接按照运算符的优先级进行计算。

中缀表达式转换为后缀表达式的基本原理如下:1. 创建一个栈,用于存储运算符。

2. 从左到右扫描中缀表达式中的每个字符。

3. 如果是操作数,直接输出到结果字符串。

4. 如果是运算符,比较当前运算符的优先级与栈顶运算符的优先级。

a. 如果栈为空或者栈顶元素是左括号 "(", 将当前运算符压入栈中。

b. 如果当前运算符的优先级高于栈顶运算符的优先级,或者栈顶元素是右括号")", 将当前运算符压入栈中。

c. 如果当前运算符的优先级低于或等于栈顶运算符的优先级,将栈顶运算符弹出并输出到结果字符串,然后重复步骤 4。

5. 当扫描完中缀表达式后,将栈中的所有运算符依次弹出并输出到结果字符串。

6. 将中缀表达式转换为后缀表达式后,按照后缀表达式的规则进行求值。

三、实验步骤1. 定义一个函数,用于判断字符是否为操作数。

2. 定义一个函数,用于判断字符是否为运算符。

3. 定义一个函数,用于判断运算符的优先级。

4. 定义一个函数,用于将中缀表达式转换为后缀表达式。

5. 定义一个函数,用于求值后缀表达式。

6. 编写主函数,实现中缀表达式的求值。

四、实验代码```pythondef is_operand(c):return c.isdigit()def is_operator(c):return c in ['+', '-', '', '/', '(', ')']def precedence(op):if op in ['+', '-']:return 1if op in ['', '/']:return 2return 0def infix_to_postfix(expression):stack = []postfix = []for c in expression:if is_operand(c):postfix.append(c)elif c == '(':stack.append(c)elif c == ')':while stack and stack[-1] != '(':postfix.append(stack.pop())stack.pop()else:while stack and precedence(stack[-1]) >= precedence(c): postfix.append(stack.pop())stack.append(c)while stack:postfix.append(stack.pop())return postfixdef evaluate_postfix(postfix):stack = []for c in postfix:if is_operand(c):stack.append(int(c))else:b = stack.pop()a = stack.pop()if c == '+':stack.append(a + b)elif c == '-':stack.append(a - b)elif c == '':stack.append(a b)elif c == '/':stack.append(a / b)return stack[0]def evaluate_infix(expression):postfix = infix_to_postfix(expression)return evaluate_postfix(postfix)# 主函数if __name__ == '__main__':expression = input("请输入中缀表达式:")result = evaluate_infix(expression)print("结果为:", result)```五、实验结果与分析1. 输入中缀表达式 "3 + 4 2",程序输出结果为 11,与预期一致。

C#中缀表达式转换为后缀表达式算法及后缀表达式计算算法的实现

C#中缀表达式转换为后缀表达式算法及后缀表达式计算算法的实现

/*名称:中缀表达式转换为后缀表达式算法及后缀表达式计算算法的实现内容:1、掌握栈的存储结构的C语言描述2、掌握中缀表达式转换为后缀表达式的算法实现3、掌握后缀表达式计算算法的实现要求:程序功能包括:主程序;表达式的输入、转换;后缀表达式的输出、计算和数据的输出。

名称二叉树的建立与遍历及二叉树中序线索化及线索化遍历的实现内容掌握二叉树的建立与遍历的算法实现掌握二叉树中序线索化及线索化遍历的算法实现要求程序功能包括:主程序;二叉树的建立、二叉树的遍历(前序、中序、后序)、二叉树中序线索化、线索化遍历和输出等实验报告:程序流程图;上机通过的程序(清单);总结二叉树遍历的特点*//*函数:1、线索二叉树(左孩子、右孩子、左线索标志、右线索标志、双亲、数据域)2、建立二叉树3、前、中、后序扫描二叉树4、中序线索化二叉树5、中序遍历线索二叉树6、线索二叉树查找7、线索二叉树插入功能:1、二叉树的输入实现(输入根、左、右的顺序,当左或右为空时输入0,以‘#’结束输入)(输入优化)2、前、中、后序扫描二叉树输出扫描结果3、二叉树中序线索化4、二叉树线索化遍历/*#include <stdio.h>#include <stdlib.h>#include <conio.h>#define maxsize 100typedef char datatype;typedef struct node{int ltag,rtag;datatype data;struct node *lchild,*rchild;//*parent;} bitree;bitree *root;bitree *pre;bitree *Q[maxsize];bitree *creatree(){char ch;int front,rear;//队头、队尾指针bitree *root,*s;root=NULL;//置空二叉树front=1;rear=0;//置空队列printf("\t\t>>>请输入二叉树(无孩子输入'@'并以'#'结束):\n\t\t");ch=getchar();//输入第一个字符while(ch!='#')//不是结束符时重复做{s=NULL;if(ch!='@')//@表示虚结点,不是虚结点时建立新结点{s=(bitree *)malloc(sizeof(bitree));s->data=ch;s->lchild=NULL;s->rchild=NULL;s->ltag=0;s->rtag=0;}rear++;Q[rear]=s;//将虚结点指针NULL或新结点地址入队if(rear==1) root=s;//输入的第一个结点为根结点else{if(s && Q[front])//孩子和双亲结点均不是虚结点if(rear%2==0) Q[front]->lchild=s;//rear为偶数,新结点为左孩子else //rear为奇数Q[front]->rchild=s;//新结点是右孩子if(rear%2==1) front++;//结点*Q[front]的两个孩子已经处理完毕,出队列}ch=getchar();//输入下一个字符}return root;//返回根指针}//关于建立新树:输入处理(关于完全二叉树)//中序遍历void inorder(bitree *t){if(t)//二叉树非空{inorder(t->lchild);//中序遍历t的左子树printf("%c ",t->data);//访问结点tinorder(t->rchild);//中序遍历t的右子树}}//前序遍历void preorder(bitree *t){if(t)//二叉树非空{printf("%c ",t->data);//访问结点tpreorder(t->lchild);//中序遍历t的左子树preorder(t->rchild);//中序遍历t的右子树}}//后序遍历void postorder(bitree *t){if(t)//二叉树非空{postorder(t->lchild);//中序遍历t的左子树postorder(t->rchild);//中序遍历t的右子树printf("%c ",t->data);//访问结点t}}void inthread(bitree *p)//将二叉树p中序线索化,线索标志初值为0 {if(p!=NULL){inthread(p->lchild);//左子树线索化if(p->lchild==NULL) p->ltag=1;//建立左线索标志if(p->rchild==NULL) p->rtag=1;//建立右线索标志if(pre!=NULL){if(pre->rtag==1)//p无右子树pre->rchild=p;//右线索p->rchild为pif(pre->ltag==1)//p无左子树pre->lchild=pre;//左线索p->lchild为pre}pre=p;inthread(p->rchild);//右子树线索化}}//在中序线索树中找结点*p的中序后继bitree *inordernext(bitree *p){bitree *q;if(p->rtag==1)//p右子树为空return (p->rchild);//p->rchild是右线索,指向p的后继else //p的右子树非空{q=p->rchild;//从p的右孩子开始查找while(q->ltag==0)//当q不是左下结点时,继续查找q=q->lchild;return(q);}}//遍历中序线索二叉树pvoid travereinthread(bitree *p){if(p!=NULL)//非空树{while(p->ltag==0)//找中序序列的开始结点p=p->lchild;do{printf("%c ",p->data);//访问结点pp=inordernext(p);//找p的中序后继结点}while(p!=NULL);}}void main(){bitree *p;int a=0;printf("\t\t**********************************************\n");printf("\t\t ************二叉树************\n");printf("\t\t**********************************************\n\n");p=creatree();//创建二叉树printf("\n");printf("\t\t二叉树的前序遍历结果为:\n");//前序遍历printf("\t\t"); preorder(p); printf("\n");printf("\t\t二叉树的中序遍历结果为:\n");//中序遍历printf("\t\t"); inorder(p); printf("\n");printf("\t\t二叉树的后序遍历结果为:\n");//后序遍历printf("\t\t"); postorder(p); printf("\n");inthread(p);//中序线索化printf("\t\t二叉树的中序线索化遍历结果为:\n");//后序遍历printf("\t\t");travereinthread(p);//中序线索话遍历printf("\t\t");getch();}*//*//在结点p、p的右子树之间插入新结点qinsertright(bithptr *p,bithptr *q){bithptr *s;s=inordernext(p);//查找p的原中序后继结点q->ltag=1;//建立q的左线索标志q->lchild=p;//q的中序前趋为pq->rtag=p->rtag;q->rchild=p->rchild;//q的右子树或右线索等于原p的右子树或右线索p-ratag=0;p->rchild=q;//新结点q作为p的右孩子if((s!=NULL)&&(s->ltag==1))s->lchild=q;//结点s的左链是线索,s的前趋是p}*//*#include <stdio.h>#include <stdlib.h>#include <conio.h>#include <math.h>typedef struct node//定义栈结构体类型{bool n;//标志操作数和操作符char operate;//操作符float num; //操作数struct node *next;} stack;struct changenum//临时变量{bool w;float num;char op;stack *q;} ;stack *InitStack()//初始化堆栈{stack *S;S = (stack *)malloc(sizeof(stack));S->n=0;S->num=0;S->operate=0;S->next=NULL;return S;}stack *push(stack *top,bool n,float num,char operate)//进栈函数{stack *p;p=(stack *)malloc(sizeof(stack));//生成新节点if(n==0)//进栈的为浮点数{p->n=0;p->operate=NULL;p->num=num;}if(n==1)//进栈的为操作符{p->n=1;p->operate=operate;p->num=NULL;}p->next=top;top=p;return p;}changenum *pop(stack *top)//退栈函数{stack *p;changenum *sp;sp=(changenum *)malloc(sizeof(changenum));if(top->next==NULL) {printf("underflow!\n");return NULL;}//栈下溢else//退栈操作{p=top;top=top->next;sp->q=top;sp->num=p->num;sp->op=p->operate;sp->w=0;return sp;}}//*******************************************//****************栈定义及操作***************//后缀表达式的存储//*******************************************typedef struct node2{bool n;//标志操作数和操作符float num;//操作数char operate;//操作符struct node2 *front,*rear,*next;//队头队尾指针} squeue; //定义队列类型squeue *q;squeue *InitQueue()//初始化队列{squeue *Q;Q = (squeue *)malloc(sizeof (squeue));Q->n=0;Q->front=Q;Q->num=12345;Q->operate=0;Q->front->next=NULL;Q->rear =Q;return Q;}void enqueue(squeue *q,bool n,float number,char op)//入队操作{if(op==')') ;else{q->rear->next=(squeue *)malloc(sizeof(squeue));q->rear=q->rear->next;if(n==0){q->rear->n=0;q->rear->operate=NULL;q->rear->num=number;}if(n==1){q->rear->n=1;q->rear->operate=op;q->rear->num=NULL;}q->rear->next=NULL;}}changenum *dequeue(squeue *q)//出队操作{squeue *s;changenum *sp;sp=(changenum *)malloc(sizeof(changenum));if(q->front->next==NULL) {sp->num=q->num;sp->w=q->n;} else{s=q->front->next;q->front->next=s->next;sp->w=s->n;sp->num=s->num;sp->op=s->operate;}return sp;}//*******************************************//****************队定义及操作***************//实现表达式的临时存储//*******************************************int priority(char ch)//操作符及操作数优先级判断{switch(ch){case'+': case'-': return 2;case'*': case'/':return 3;case'(': case'#': return 1;case')': return 4;case ' ':return 10;case'.': case'0': case'1': case'2':case'3': case'4': case'5': case'6':case'7': case'8': case'9': return 0;default:printf("ERROR!"); return 5;}}changenum *getlist(char ch)//将字符数组转为float类型变量{changenum *sp;sp=(changenum *)malloc(sizeof(changenum));if(priority(ch)==0){sp->w=0;int p=1;float sum=0,point=0;char a[40];int m=0;int n=1;for(int i=0;i<=39;i++)a[i]=0;while(ch!='.'&&priority(ch)==0){a[m]=ch; sum=sum*10+(a[m]-'0'); m++;//整数部分ch=getchar();}if(ch=='.'){ch=getchar();while(priority(ch)==0)//小数部分处理{a[m+n]=ch; point=point*10+(a[m+n]-'0');p=p*10; n++;ch=getchar();}}sum=sum+point/p;//转为浮点数sp->num=sum;sp->op=ch;return sp;}else{sp->w=1;sp->num=100;sp->op=100;return sp;}}float change()//输入中缀表达式并转换为后缀表达式、输出后缀表达式并计算结果{stack *formula1;squeue *formula2,*formula4;stack *formula3;char a,ch;bool i; changenum *mark,*sign;formula2=InitQueue();formula4=InitQueue();formula1=InitStack();formula3=InitStack();formula3=push(formula3,1,0,'#');formula1=push(formula1,1,0,'#');printf("请输入表达式以#结束:\n");ch=getchar();do{mark=getlist(ch);i=mark->w;if(i==0){enqueue(formula2,0,mark->num,0);enqueue(formula4,0,mark->num,0);ch=mark->op;free(mark);/ /将操作数入队}else{switch(ch)//操作符处理{case '(' : formula1=push(formula1,1,0,ch); break; //将做括号压入栈Scase ')' :if(formula1->operate=='#') {printf("括号不匹配!!!\n");return 1;}else{do{sign=pop(formula1);formula1=sign->q;a=sign->op;if(a=='(') break;else if(priority(a)==4) ;else{enqueue(formula2,1,0,a);enqueue(formula4,1,0,a);}}while(a!='#');if(a=='#') {printf("括号不匹配!!!\n");return 1;}}case '+' :case '-' :case '*' :case '/' :while (formula1->operate!='#' && formula1->operate!='(' && priority(formula1->operate)>=priority(ch)){sign=pop(formula1);formula1=sign->q;enqueue(formula2,1,0,sign->op);enqueue(formula4,1,0, sign->op);}formula1=push(formula1,1,0,ch);break;case '#' : break;default: printf("ERROR!!!\n");return 1;}ch=getchar();}}while(ch!='#');//表达式扫描结束条件//表达式扫描结束后若栈中还有元素则依次弹出输入的后缀表达式中while (formula1->operate!='#'){sign=pop(formula1);formula1=sign->q;if(sign->op=='(') {printf("括号不匹配!!!\n");return 1;}else {enqueue(formula2,1,0,sign->op);enqueue(formula4,1,0,sign->op);}}printf("后缀表达式为:\n");do//后缀表达式的输出{mark=dequeue(formula2);if(mark->num==12345) break;if(mark->w==0){printf("%.3f",mark->num);free(mark);}else{printf("%c",mark->op);free(mark);}}while(1);printf("\n");/////////////////////////////////////////////////////////后缀表达式的计算////////////////////////////////////////////////////////float x,y;mark=dequeue(formula4);while (mark->num!=12345)//若队不为空{if (mark->w==0){formula3=push(formula3,0,mark->num,0);free(mark);}else{sign=pop(formula3);y =sign->num; formula3=sign->q;free(sign);//两次取操作数并交换次序sign=pop(formula3);x =sign->num; formula3=sign->q;free(sign);switch (mark->op)//计算周缀表达式的值{case '+' : formula3=push(formula3,0, x + y,0);break;case '-' : formula3=push(formula3,0, x - y,0);break;case '*' : formula3=push(formula3,0, x * y,0);break;case '/' : formula3=push(formula3,0, x / y,0);break;default:printf("ERROR!!!\n");return 0;}}mark = dequeue(formula4);//出队操作}printf("表达式的计算结果为:%.3f\n",pop(formula3)->num);return 0;}void main(){float sum;bool a;sum=change();//计算并转换后缀表达式getch();}*/。

表达式求值 实验报告

表达式求值 实验报告

表达式求值实验报告表达式求值实验报告一、引言表达式求值是计算机科学中一个重要的概念,它涉及到对数学表达式的计算和求解。

在本次实验中,我们将探讨表达式求值的相关算法和实现方法,并通过编程实现一个简单的表达式求值器。

二、算法原理1. 表达式的表示方法在计算机中,我们通常使用字符串来表示表达式。

例如,一个简单的数学表达式"2 + 3 * 4"可以表示为字符串"2+3*4"。

在实现表达式求值的算法时,我们需要将字符串中的数字和运算符进行分离,以便进行后续的计算。

2. 中缀表达式转后缀表达式为了方便计算,我们通常将中缀表达式转换为后缀表达式。

后缀表达式也称为逆波兰表达式,它的特点是运算符位于操作数的后面。

例如,上述的中缀表达式"2+3*4"可以转换为后缀表达式"234*+"。

转换的方法可以通过使用栈来实现。

3. 后缀表达式求值得到后缀表达式后,我们可以通过扫描表达式并使用栈来求解。

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

最终,栈中的唯一元素即为表达式的求值结果。

三、实验过程1. 数据结构设计为了实现表达式求值器,我们需要设计相应的数据结构。

在本次实验中,我们选择使用栈来存储操作数和运算符。

2. 中缀表达式转后缀表达式首先,我们需要编写一个函数来将中缀表达式转换为后缀表达式。

该函数的实现可以通过使用栈和遍历字符串来实现。

具体的步骤如下:- 创建一个空栈和一个空字符串用于存储后缀表达式。

- 从左到右遍历中缀表达式的每个字符。

- 如果遇到操作数,直接将其添加到后缀表达式字符串中。

- 如果遇到运算符,将其与栈顶的运算符进行比较:- 如果栈为空或栈顶为左括号"(",则直接将运算符入栈。

- 如果栈顶的运算符优先级低于当前运算符,则将当前运算符入栈。

- 如果栈顶的运算符优先级高于或等于当前运算符,则将栈顶的运算符弹出并添加到后缀表达式字符串中,直到栈顶的运算符优先级低于当前运算符或栈为空。

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

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

数据结构表达式求值实验报告一、实验目的本次实验的主要目的是通过实现表达式求值的程序,深入理解数据结构和算法在解决实际问题中的应用。

具体包括掌握栈这种数据结构的操作和使用,熟悉表达式的转换和计算过程,提高编程能力和问题解决能力。

二、实验环境本次实验使用的编程语言为C++,开发工具为Visual Studio 2019。

三、实验原理表达式求值是程序设计中的一个常见问题,通常采用栈这种数据结构来实现。

表达式可以分为中缀表达式、后缀表达式和前缀表达式。

中缀表达式是我们日常使用的表达式形式,如“2 +3 4”,但直接对中缀表达式求值比较复杂。

而后缀表达式(如“2 3 4 +”)和前缀表达式(如“+2 3 4”)求值相对简单。

因此,在实现表达式求值时,通常先将中缀表达式转换为后缀表达式,然后对后缀表达式进行求值。

转换过程中,使用两个栈,一个用于存储操作数,另一个用于存储运算符。

求值过程中,根据后缀表达式的特点,从左到右依次处理操作数和运算符,进行相应的计算。

四、实验步骤1、定义数据结构定义栈类,用于存储操作数和运算符。

定义一个结构体来表示操作数和运算符。

2、中缀表达式转后缀表达式从左到右扫描中缀表达式。

遇到操作数,直接输出。

遇到运算符,根据其优先级与栈顶运算符的优先级进行比较,决定入栈或出栈操作。

3、后缀表达式求值从左到右扫描后缀表达式。

遇到操作数,入栈。

遇到运算符,从栈中取出两个操作数进行计算,将结果入栈。

4、主函数输入中缀表达式。

调用转换函数和求值函数,输出计算结果。

五、实验代码```cppinclude <iostream>include <stack>include <string>//定义操作符的优先级int priority(char op) {if (op =='+'|| op =='')return 1;if (op ==''|| op =='/')return 2;return 0;}//中缀表达式转后缀表达式std::string infixToPostfix(std::string infix) {std::stack<char> opStack;std::string postfix ="";for (char c : infix) {if (isdigit(c)){postfix += c;} else if (c =='('){} else if (c ==')'){while (!opStackempty()&& opStacktop()!='('){postfix += opStacktop();opStackpop();}opStackpop();//弹出'('} else {while (!opStackempty()&& priority(opStacktop())>=priority(c)){postfix += opStacktop();opStackpop();}opStackpush(c);}}while (!opStackempty()){postfix += opStacktop();}return postfix;}//后缀表达式求值int evaluatePostfix(std::string postfix) {std::stack<int> operandStack;for (char c : postfix) {if (isdigit(c)){operandStackpush(c '0');} else {int operand2 = operandStacktop();operandStackpop();int operand1 = operandStacktop();operandStackpop();switch (c) {case '+':operandStackpush(operand1 + operand2);break;case '':operandStackpush(operand1 operand2);break;case '':operandStackpush(operand1 operand2);break;case '/':operandStackpush(operand1 / operand2);break;}}}return operandStacktop();}int main(){std::string infixExpression;std::cout <<"请输入中缀表达式: ";std::cin >> infixExpression;std::string postfixExpression = infixToPostfix(infixExpression);int result = evaluatePostfix(postfixExpression);std::cout <<"表达式的计算结果为: "<< result << std::endl;return 0;}```六、实验结果输入不同的中缀表达式,如“2 +3 4”“( 2 + 3 )4”等,程序能够正确地将其转换为后缀表达式,并计算出结果。

数据结构实验报告 实验二 中缀表达式转化为后缀表达式算法

数据结构实验报告 实验二 中缀表达式转化为后缀表达式算法

tempIndex++;
chars = tempCh[tempIndex];
}
td.d = atof(assch); push(&tds,td);
//将取出的操作数入栈
k = tempIndex;
continue;
} else if(chars == ' ')
// 如是' '则直接跳过
{
-2-
k++;
二.实验目的:
结合堆栈入栈出栈的特点解决实际问题。
三.主要程序代码分析:
typedef struct {
OpNode opNode[100]; int top; int size; }OpStack; void Op_init(OpStack *ops) { ops->top = 0; ops->size = 0; }
//创建字符栈 //存放栈顶的数 //存放当前栈的大小
//对字符栈的初始化
-1-
void Op_push(OpStack *ops,OpNode op)
//字符栈的入栈操作
{
ops->size++;
ops->opNode[(ops->top)++] = op;
} OpNode Op_pop(OpStack *ops)
{
int len = ops->size;
return ops->opNode[len - 1];
}
while(tempCh[k] != '\0')
//计算后缀表达式
{
char chars = tempCh[k]; if(chars >= '0' && chars <= '9' || chars == '.') //判断是否为操作数

用栈和二叉树实现中缀表达式转后缀表达式构建计算机并求值实验报告

用栈和二叉树实现中缀表达式转后缀表达式构建计算机并求值实验报告

实验报告姓名:黄雄镖学号:13331093院系专业:软件学院2013级教务4班完成日期:2014 年10 月20 日实验题目:实现一个较为通用的计算器需求分析:实现一个包含加减乘除运算的较为通用的计算器,操作数可能是负数,并且可能是多位数。

运算式中可以有括号和多余空格。

计算器对负号不敏感, 形如1+-1或者1+(-1)都是可以接受的。

概要设计思路: 将表达式的中缀表达式转换成后缀表达式,然后利用一个栈或者建立二叉树对后缀表达式进行求值。

由于多位数在转为后缀表达式时会分不清, 故在每个数和运算符后面加上一个空格作为区别在主程序中调用用栈求值的计算器类和用二叉树计算的计算器类, 输出算式的结果13331093_03.h里存放用栈求值的计算器类13331093_03_tree.h里存放用二叉树计算的计算器类13331093_03.h的类里主要包括:获得算术表达式的函数getexpression(string expression), expression为所要计算的算术表达式计算函数calculate(string num2, string num1, string op), 输入为两个数(字符串形式)和一个操作符, 返回值为计算结果(字符串形式)返回中缀表达式函数ShowMiddleExpression(), 返回的中缀表达式为字符串形式RidSpace(string origin)用于去除输入中多余的空格, 输入为要除去空格的算术表达式, 返回去掉空格的算术表达式MidToLast(string str)中缀表达式转后缀表达式获得后缀表达式函数GetLastExpression(), 返回的后缀表达式为字符串形式用栈执行计算后缀表达式函数exe(), 返回计算结果为字符串形式13331093_03_tree.h类里主要包括:获得算术表达式的函数getexpression(string expression), expression为所要计算的算术表达式计算函数calculate(string num2, string num1, string op), 输入为两个数(字符串形式)和一个操作符, 返回值为计算结果(字符串形式)返回中缀表达式函数ShowMiddleExpression(), 返回的中缀表达式为字符串形式RidSpace(string origin)用于去除输入中多余的空格, 输入为要除去空格的算术表达式, 返回去掉空格的算术表达式MidToLast(string str)中缀表达式转后缀表达式获得后缀表达式函数GetLastExpression(), 返回的后缀表达式为字符串形式生成一颗二叉树的函数makeTree(TNode *&p)后序遍历二叉树并计算的函数PostOrder(TNode *p), 返回计算结果为字符串形式a.调试过程遇到的问题与解决方案:遇到的问题:调试过程中出现程序崩溃的现象, 后来debug发现是没有考虑到执行运算过程中出现的-()的情况原因:没有考虑-()的情况, 导致栈为空的时候还弹出元素解决方案:特殊处理这种情况b.时间和空间复杂度:除去输入中空格的操作的时间复杂度为O(n),中缀表达式转后缀表达式的时间复杂度为O(n), 用栈执行运算的时间复杂度为O(n),后序遍历二叉树的时间复杂度为O(n) 所以用栈计算或者用二叉树计算的操作的时间复杂度为都是O(n)栈属于线性表, 故用栈计算的空间复杂度为O(n)用二叉树计算的空间复杂度也是O(n)主程序:输入一个整数m,代表有m个输入接下来有m行,每一行输入你要计算的式子13331093_03.h:含有用stack计算的计算器类用法:calculator c_stack 声明一个计算器对象c_stack.getexpression(expression) 把算术表达式存入计算器中expression为所要计算的算术表达式c_stack.GetLastExpression() 获取算术表达式的后缀表达式c_stack.exe() 获取计算结果13331093_03_tree.h:含有用二叉树计算的计算器类用法:calculator_tree c_tree 声明一个计算器对象c_tree.getexpression(expression) 把算术表达式存入计算器中expression为所要计算的算术表达式c_tree.GetLastExpression() 获取算术表达式的后缀表达式c_tree.makeTree(tree) 建立一棵二叉树c_tree.PostOrder(tree) 后序遍历二叉树并返回计算结果测试结果在主程序中调用用栈求值的计算器类和用二叉树计算的计算器类, 并对输入表达式进行两种方法所生成的后缀表达式和结果的对比测试代码在test.cpp中测试输入:11-(12.34)-11+-21+(-2)11 + 23 * 32/4-8-1.234/5 *(1 +3)2.333*4-(3+(-5))12345+5432.1/(-12345)-(100 ) * 0.5 -(-22.22)1234/-123+3.333-( 123*50 ) / 2.2测试结果如下:另外我用计算器算过, 结果是正确的实验心得通过这次实验, 我对栈和二叉树的理解加深了很多。

数据结构实验报告总结

数据结构实验报告总结

数据结构实验报告总结Abstract本实验报告总结了在数据结构实验中进行的一系列实验,包括线性表、栈、队列、二叉树以及图等数据结构的实现与运用。

通过实验,我们对数据结构的基本概念、操作和应用有了更深入的理解。

本报告将对每个实验进行总结,并分析实验中的问题和解决方案。

1. 线性表实验在线性表实验中,我们熟悉了线性表的基本概念和操作。

实验中,我们使用数组和链表两种不同的存储结构实现了线性表,并比较了它们的优缺点。

我们还学习了线性表的顺序查找和二分查找算法,并分析了它们的时间复杂度。

通过这些实验,我们深入理解了线性表的特性和算法。

2. 栈实验栈是一种特殊的线性表,具有“先进后出”的特性。

在栈实验中,我们实现了栈的基本操作,包括进栈、出栈和判断栈是否为空等。

我们还利用栈实现了括号匹配和中缀表达式转后缀表达式的算法。

通过这些实验,我们学会了如何运用栈进行简单的计算和语法分析。

3. 队列实验队列是一种“先进先出”的线性表,对于某些应用场景非常重要。

在队列实验中,我们实现了队列的基本操作,包括入队、出队和判断队列是否为空等。

我们还学习了循环队列和链式队列的实现,并比较它们的优缺点。

通过这些实验,我们掌握了队列的应用和效率分析。

4. 二叉树实验二叉树是一种非常常见的数据结构,具有良好的应用潜力。

在二叉树实验中,我们实现了二叉树的基本操作,包括插入节点、删除节点和查找节点等。

我们还学习了二叉树的遍历算法,包括前序、中序和后序遍历,并分析了它们的应用场景和时间复杂度。

通过这些实验,我们深入了解了二叉树的特性和算法。

5. 图实验图是一种非常复杂的数据结构,用于解决实际问题时非常有用。

在图实验中,我们实现了图的基本操作,包括添加节点、添加边和遍历图等。

我们还学习了图的深度优先搜索和广度优先搜索算法,并比较它们的优缺点。

通过这些实验,我们掌握了图的应用和算法分析。

总结通过这些数据结构实验,我们不仅掌握了各种数据结构的基本概念和操作,还学会了运用它们解决实际问题的方法。

用栈实现中缀表达式转后缀表达式并构建计算机求值

用栈实现中缀表达式转后缀表达式并构建计算机求值

#include <string>#include <stack>#include <iostream>#include <sstream>#include <iomanip>using namespace std;class calculator{public:calculator() {}calculator(string expression) {getexpression(expression);}//获得算术表达式void getexpression(string expression) {e = expression;}~calculator() {}//返回中缀表达式string ShowMiddleExpression() {return e;}//计算函数, 输入为两个数和一个操作符, 返回值为计算结果(字符串形式) string calculate(string num2, string num1, string op) {double n2, n1;string result;stringstream x;x << num2;x >> n2;x.clear();x << num1;x >> n1;x.clear();if (op == "+")x << (n2 + n1);if (op == "-")x << (n2 - n1);if (op == "*")x << (n2 * n1);if (op == "/")x << (n2 / n1);x >> result;x.clear();return result;}//判别符号的优先级int Priority(char a) {if (a == '(')return 0;else if (a == '+' || a == '-')return 1;else if (a == '*' || a == '/')return 2;return 0;}//用于去除输入中多余的空格输入为要除去空格的算术表达式返回去掉空格的算术表达式string RidSpace(string origin) {string transfer;for (int i = 0; i < origin.length(); i++) {if (origin[i] != ' ')transfer += origin[i];}return transfer;}//中缀表达式转后缀表达式, 因为要兼容多位数, 括号, 负数和小数等功能,//由于多位数在转为后缀表达式时会分不清, 故在每个数和运算符后面加上一个空格作为区别//expression为输出的后缀表达式string MidToLast(string str) {str = RidSpace(str);string expression = "";string number = "";char x;stack<char> op;for (int i = 0; i < str.length(); ) {//第一位做特殊处理判断是否为负号if (i == 0 && str[i] == '-') {number = "-";i++;}x = str[i];//录入数字if ((x >= '0' && x <= '9') || number == "-" || x == '.') {while ((str[i] >= '0' && str[i] <= '9') || str[i] == '.') {number += str[i];i++;}expression += number;//加空格以区别expression += " ";number = "";continue;} else {//判断是括号还是运算符if (x == '(') {op.push(x);//判断是否为负号if (str[i+1] == '-') {number = "-";i++;}} else {//遇到右括号直接弹出运算符栈里的运算符到表达式中运算符后加空格以区别if (x == ')') {while (op.top() != '(') {expression += op.top();expression += " ";op.pop();}//弹出右括号op.pop();} else {//弹出栈中优先级较高的运算符运算符后加空格以区别while (!op.empty() && (Priority(op.top()) >= Priority(x))) {expression += op.top();expression += " ";op.pop();}//判断是否为负号if (str[i+1] == '-') {number = "-";i++;}//将运算符压入栈op.push(x);}}}i++;}while (!op.empty()) {expression += op.top();expression += " ";op.pop();}return expression;}//获得后缀表达式string GetLastExpression() {return MidToLast(RidSpace(e));}string exe() {//获取后缀表达式string le = GetLastExpression();string tem = "";stack<string> num;for (int i = 0; i < le.length(); ) {while (le[i] != ' ') {tem += le[i];i++;}//若为数字, 压栈if (tem.length() > 1 || (tem.length() == 1 && tem[0] >= '0' && tem[0] <= '9')) { num.push(tem);} else {//若为运算符, 执行运算后压栈//处理如-()的情况if (num.empty()) {tem = "-";i++;continue;}string tem1 = num.top();num.pop();if (!num.empty()) {string tem2 = num.top();num.pop();num.push(calculate(tem2, tem1, tem));} else {tem1 = "-" + tem1;num.push(tem1);}}i++;tem = "";}return num.top();}private:string e;};。

将中缀表达式转换为后缀表达式并计算

将中缀表达式转换为后缀表达式并计算

《数据结构》实验报告◎实验题目:使用键盘输入表达式,计算表达式的值并输出;将表达式转化成后缀表达式输出,利用后缀表达式求表达式的值并输出。

◎实验目的:使用栈的操作编写关于数据结构的程序。

◎实验内容:写出程序并上机调试、通过。

一、需求分析1、演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“请输入表达式”时输入中缀表达式。

然后计算机终端输出转换后的后缀表达式及计算后的结果。

2、程序执行的命令包括:(1)构造链栈;(2)输入数据;(3)判断输入的表达式是否为非法表达式;(4)将中缀表达式转换为后缀表达式;(5)计算表达式的值;(6)输出。

(7)结束4、本程序能将中缀表达式转换为后缀表达式,并且能计算表达式的值。

5、输入及输出示例:例1:请输入表达式6+3*(6+5)后缀表达式:6 3 6 5 + * +计算结果为:39Press any key to continue例2:请输入表达式6-3*(7+1ERROR:表达式错误Press any key to continue二概要设计1.基本操作(1)、struct node操作结果:创建结构体(2)、int Searchexpression(char string1[])初始条件:表达式string1已经存在。

操作结果:判断表达式是否非法(3)、struct node *Initialization()操作结果:创建栈链。

(4)、struct node *assort(struct node *s)初始条件:string1、string2已存在。

操作结果:将中缀表达式转换为后缀表达式并存在string2中。

(5)、struct node *calcolate(struct node *s)操作结果:求出表达式的值2、模块调用图三详细设计1、每个模块:(1) 定义结构体struct node{char data;int num;struct node *next;};(2) 判断表达式是否非法int Searchexpression(char string1[]){int i1,b1,b2;int m;m=strlen(string1);if(string1[0]<'0'||string1[0]>'9'){printf("ERROR:表达式缺操作数!\n");return(WRONG);}for(i1=0;i1<=m;i1++){if(string1[i1]=='(')b1++;elseif(string1[i1]==')')b2++;}if(b1!=b2){printf("ERROR:缺少括号\n");return(WRONG);}for(i1=0;i1<m;i1++)if('0'<=string1[i1]&&string1[i1]<='9'&&'0'<=string1[i1+1]&&str ing1[i1+1]<='9'){ printf("ERROR:表达式缺操作符!\n");return(WRONG);}for(i1=0;i1<=m;i1++)if(string1[i1]=='+'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||stri ng1[i1+1]=='*'||string1[i1+1]=='/')){ printf("ERROR:表达式缺操作数!\n");return(WRONG);}elseif(string1[i1]=='-'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||strin g1[i1+1]=='*'||string1[i1+1]=='/')){ printf("ERROR:表达式缺操作数!\n");return(WRONG);}elseif(string1[i1]=='*'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||strin g1[i1+1]=='*'||string1[i1+1]=='/')){printf("ERROR:表达式缺操作数!\n");return(WRONG);}elseif(string1[i1]=='/'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||string1[i1+1]=='*'||string1[i1+1]=='/')){printf("ERROR:表达式缺操作数!\n");return(WRONG);}return(RIGHT);}(3)、将中缀表达式转换为后缀表达式struct node *assort(struct node *s)//输入字符串{struct node *p,*top;int i;top=s;int m;char a;m=strlen(string1);for(i=0;i<=m;i++){a=string1[i];if('0'<=string1[i]&&string1[i]<='9'){string2[j]=string1[i];j++;}else{switch(a){case '(':{p=(struct node *)malloc(sizeof(struct node));p->data=a;p->next=top;top=p;break;}case '*':case '/':string2[j]=' ';j++;if((top->data=='*')||(top->data=='/')){string2[j]=top->data;j++; //比其高,现将栈顶运算符出栈,再进栈。

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

实验报告
姓名:黄雄镖学号:13331093
院系专业:软件学院2013级教务4班
完成日期:2014 年10 月20 日
实验题目:实现一个较为通用的计算器
需求分析:
实现一个包含加减乘除运算的较为通用的计算器,操作数可能是负数,并且可能是多位数。

运算式中可以有括号和多余空格。

计算器对负号不敏感, 形如1+-1或者1+(-1)都是可以接受的。

概要设计
思路: 将表达式的中缀表达式转换成后缀表达式,然后利用一个栈或者建立二叉树对后缀表达式进行求值。

由于多位数在转为后缀表达式时会分不清, 故在每个数和运算符后面加上一个空格作为区别
在主程序中调用用栈求值的计算器类和用二叉树计算的计算器类, 输出算式的结果
13331093_03.h里存放用栈求值的计算器类
13331093_03_tree.h里存放用二叉树计算的计算器类
13331093_03.h的类里主要包括:
获得算术表达式的函数getexpression(string expression), expression为所要计算的算术表达式计算函数calculate(string num2, string num1, string op), 输入为两个数(字符串形式)和一个操作符, 返回值为计算结果(字符串形式)
返回中缀表达式函数ShowMiddleExpression(), 返回的中缀表达式为字符串形式
RidSpace(string origin)用于去除输入中多余的空格, 输入为要除去空格的算术表达式, 返回去掉空格的算术表达式
MidToLast(string str)中缀表达式转后缀表达式
获得后缀表达式函数GetLastExpression(), 返回的后缀表达式为字符串形式
用栈执行计算后缀表达式函数exe(), 返回计算结果为字符串形式
13331093_03_tree.h类里主要包括:
获得算术表达式的函数getexpression(string expression), expression为所要计算的算术表达式计算函数calculate(string num2, string num1, string op), 输入为两个数(字符串形式)和一个操作符, 返回值为计算结果(字符串形式)
返回中缀表达式函数ShowMiddleExpression(), 返回的中缀表达式为字符串形式
RidSpace(string origin)用于去除输入中多余的空格, 输入为要除去空格的算术表达式, 返回去掉空格的算术表达式
MidToLast(string str)中缀表达式转后缀表达式
获得后缀表达式函数GetLastExpression(), 返回的后缀表达式为字符串形式
生成一颗二叉树的函数makeTree(TNode *&p)
后序遍历二叉树并计算的函数PostOrder(TNode *p), 返回计算结果为字符串形式
a.调试过程遇到的问题与解决方案:
遇到的问题:调试过程中出现程序崩溃的现象, 后来debug发现是没有考虑到执行运算过程中出现的-()的情况
原因:没有考虑-()的情况, 导致栈为空的时候还弹出元素
解决方案:特殊处理这种情况
b.时间和空间复杂度:
除去输入中空格的操作的时间复杂度为O(n),中缀表达式转后缀表达式的时间复杂度为O(n), 用栈执行运算的时间复杂度为O(n),后序遍历二叉树的时间复杂度为O(n) 所以用栈计算或者用二叉树计算的操作的时间复杂度为都是O(n)
栈属于线性表, 故用栈计算的空间复杂度为O(n)
用二叉树计算的空间复杂度也是O(n)
主程序:输入一个整数m,代表有m个输入
接下来有m行,每一行输入你要计算的式子
13331093_03.h:含有用stack计算的计算器类
用法:
calculator c_stack 声明一个计算器对象
c_stack.getexpression(expression) 把算术表达式存入计算器中expression为所要计算的算术表达式
c_stack.GetLastExpression() 获取算术表达式的后缀表达式
c_stack.exe() 获取计算结果
13331093_03_tree.h:含有用二叉树计算的计算器类
用法:
calculator_tree c_tree 声明一个计算器对象
c_tree.getexpression(expression) 把算术表达式存入计算器中expression为所要计算的算术表达式
c_tree.GetLastExpression() 获取算术表达式的后缀表达式
c_tree.makeTree(tree) 建立一棵二叉树
c_tree.PostOrder(tree) 后序遍历二叉树并返回计算结果
测试结果
在主程序中调用用栈求值的计算器类和用二叉树计算的计算器类, 并对输入表达式进行两种方法所生成的后缀表达式和结果的对比测试代码在test.cpp中
测试输入:
11
-(12.34)
-1
1+-2
1+(-2)
11 + 23 * 32/4-8
-1.234/5 *(1 +3)
2.333*4-(3+(-5))
12345+5432.1/(-12345)
-(100 ) * 0.5 -(-22.22)
1234/-123+3.333
-( 123*50 ) / 2.2
测试结果如下:
另外我用计算器算过, 结果是正确的
实验心得
通过这次实验, 我对栈和二叉树的理解加深了很多。

还有调试中出现了点问题, 通过分析是有些情况没有考虑到, 因此写代码时一定要认真思考不同的情况。

虽然上学期写过中缀表达式转后缀表达式, 但是一看我之前写的代码, 我自己都看不懂, 所以只好重新写一遍, 这让我深刻认识到代码风格, 变量命名和注释的重要性。

列出程序文件名的清单:
13331093_03.h
13331093_03_tree.h
13331093_03.cpp
test.cpp。

相关文档
最新文档