后缀表达式求值
- 格式:doc
- 大小:58.00 KB
- 文档页数:5
堆栈和队列Content堆栈1队列2表达式计算3递归4PART THREE表达式计算•表达式的概念•后缀表达式求值•中缀表达式到后缀表达式的转换•中缀表达式:操作符在两个操作数之间的表达式•前缀表达式:操作符在两个操作数之前的表达式•后缀表达式:操作符在两个操作数之后的表达式逆波兰表达式(Reverse Polish notation ,RPN ),J. Lukasiewicz 1929示例:a + b 示例:+ a b 示例:a b +表达式:由操作数、操作符(+、-、*、\等)和界限符(括号等)组成•中缀表达式a + ( b –c )a + ba b +a b c -+计算的顺序由界符、操作符优先级决定计算的顺序只取决于操作符的扫描顺序•后缀表达式VS.对比:•操作数的顺序相同,而操作符的顺序不同;•前者的不同操作符的运算优先级存在差异,后者的所有操作符的运算优先级相同;•前者可以有界限符,后者没有界限符;后缀表达式求值算法(利用堆栈实现):1.从左往右顺序依次扫描后缀表达式中的元素:•若当前扫描元素是操作数,则将操作数进栈;•若当前扫描元素是操作符,则从栈中弹出两个操作数,并执行该操作符指定的运算,然后将计算结果进栈;2.当表达式扫描结束,弹出栈顶数据,该数据即为计算结果。
6 4 2 -/ 3 2 * + 6-24/32*+6/(4-2)+3*2= 9算法(利用堆栈实现):1.从左往右顺序依次扫描后缀表达式中的元素:•若当前扫描元素是操作数,则将操作数进栈;•若当前扫描元素是操作符,则从栈中弹出两个操作数,并执行该操作符指定的运算,然后将计算结果进栈;2.当表达式扫描结束,弹出栈顶数据,该数据即为计算结果。
6 4 2 -/ 3 2 * +6-24/32*+42=2算法(利用堆栈实现):1.从左往右顺序依次扫描后缀表达式中的元素:•若当前扫描元素是操作数,则将操作数进栈;•若当前扫描元素是操作符,则从栈中弹出两个操作数,并执行该操作符指定的运算,然后将计算结果进栈;2.当表达式扫描结束,弹出栈顶数据,该数据即为计算结果。
#include"stdio.h"#include"stdlib.h"#include"malloc.h"typedef struct {char *base;char *top;int stacksize;}SqStackchar;typedef struct {float *base;float *top;int stacksize;}SqStackint;//构造空栈SqStackchar InitStackchar(){SqStackchar S;S.base=(char *)malloc(sizeof(char));if(S.base==NULL) exit(-1);S.top=S.base;S.stacksize=100;return S;}SqStackint InitStackint(){SqStackint S;S.base=(float *)malloc(sizeof(float));if(S.base==NULL) exit(-1);S.top=S.base;S.stacksize=100;return S;}//进栈SqStackchar Pushchar(SqStackchar &S,char c){if((S.top-S.base)==S.stacksize){S.base=(char *)realloc(S.base,110*sizeof(char));if(S.base==NULL) exit(-1);S.top=S.base+S.stacksize;}*S.top++=c;return S;}SqStackint Pushint(SqStackint &S,float c){if((S.top-S.base)==S.stacksize){S.base=(float *)realloc(S.base,110*sizeof(float));if(S.base==NULL) exit(-1);S.top=S.base+S.stacksize;}*S.top++=c;return S;}//获得栈顶元素char GetTopchar(SqStackchar S){char e;if(S.top==S.base) exit(-1);e=*(S.top-1);return e;}float GetTopint(SqStackint S){float e;if(S.top==S.base) exit(-1);e=*(S.top-1);return e;}//出栈操作char Popchar(SqStackchar &S){if(S.top==S.base) exit(-1);char e;e=*--S.top;return e;}float Popint(SqStackint &S){if(S.top==S.base) exit(-1);float e;e=*--S.top;return e;}//判断该字符是数字的还是操作符int In(char c){if(c=='0'||c=='1'||c=='2'||c=='3'||c=='4'||c=='5'||c=='6'||c=='7'||c=='8' ||c=='9') return 1;else return 0;}//运算函数float Operate(float a,char theta,float b){switch(theta){case '+':return (a+b);case '-':return (a-b);case '*':return (a*b);case '/':return (a/b);default:exit(-1);}}//判断操作符的优先级char Precede(char a,char b){if((a=='('&&b!=')')||(a=='#'&&b!='#'))return '<';if(a==')')if((a=='('&&b==')')||(a=='#'&&b=='#'))return '=';if((a=='+'||a=='-')&&(b=='+'||b=='-'||b==')'||b=='#'))return '>';if((a=='+'||a=='-')&&(b=='*'||b=='/'||b=='('))return '<';if((a=='*'||a=='/')&&(b=='('))return '<';if((a=='*'||a=='/')&&(b=='+'||b=='-'||b=='*'||b=='/'||b==')'||b=='#')) return '>';}//主函数int main(){SqStackchar OPRT;SqStackint OPND;OPRT=InitStackchar();Pushchar(OPRT,'#');OPND=InitStackint();printf("请输入表达式:\n");c=getchar();float a,b;char theta;while(c!='#'||GetTopchar(OPRT)!='#'){if(In(c)){Pushint(OPND,c-48);c=getchar();while(In(c)){float e;e=GetTopint(OPND)*10+(int)(c)-48;Popint(OPND);Pushint(OPND,e);c=getchar();}}elseswitch(Precede(GetTopchar(OPRT),c)){ case '<':Pushchar(OPRT,c);c=getchar();break;case '=':Popchar(OPRT);c=getchar();break;case '>':theta=Popchar(OPRT);b=Popint(OPND);a=Popint(OPND);Pushint(OPND,Operate(a,theta,b));break;}//switch}//whileprintf("结果为:%f\n",GetTopint(OPND));return 0;}Ps.此文章来自网络,供大家学习交流。
逻辑表达式短路求值后缀表达式逻辑表达式短路求值后缀表达式的过程如下:1. 将中缀逻辑表达式转换为后缀表达式。
这个过程可以使用运算符优先级和括号来确定运算符的顺序。
2. 执行后缀表达式的求值过程。
从左到右扫描后缀表达式:- 如果遇到操作数,将其压入栈中。
- 如果遇到操作符,从栈中弹出相应数量的操作数进行运算,并将运算结果压入栈中。
- 重复上述步骤,直到扫描完后缀表达式。
3. 最终栈中剩下的元素就是整个逻辑表达式的求值结果。
例如,对于逻辑表达式 "A && B || C",其后缀表达式为 "A B&& C ||"。
假设 A = true,B = false,C = true,那么短路求值的过程如下:1. 将 A 和 B 压入栈中。
2. 遇到 "&&" 操作符,从栈中弹出 B(false),然后从栈中弹出 A(true)。
将 A && B 的结果(false)压入栈中。
3. 将 C 压入栈中。
4. 遇到 "||" 操作符,从栈中弹出 C(true),然后从栈中弹出A &&B 的结果(false)。
将 (A && B) ||C 的结果(true)压入栈中。
5. 栈中剩下的元素是最终的结果,即 (A && B) || C 的值为 true。
因此,逻辑表达式 "A && B || C" 的短路求值后缀表达式的结果为 true。
基于栈的后缀算术表达式求值c语言1. 引言1.1 概述本文将讨论基于栈的后缀算术表达式求值的实现过程。
后缀算术表达式(也称为逆波兰表达式)是一种无需括号即可进行运算的表达式表示方法,它将操作符置于操作数之后。
相较于传统的中缀表达式,在计算机程序中处理后缀表达式更为高效和简洁。
1.2 文章结构文章分为五个主要部分:引言、栈的概念及原理、后缀算术表达式的定义和转换、基于栈的后缀算术表达式求值算法实现以及结论与总结。
在引言部分,我们将首先介绍本文的概述和目标,对后续内容进行简要说明。
1.3 目的通过本文,我们旨在让读者了解栈数据结构的基本概念和原理,并且掌握如何利用栈来实现对后缀算术表达式进行求值的算法。
同时,我们将介绍后缀算术表达式的定义和转换方法,并给出基于栈实现该计算方式的详细步骤与示例代码。
通过深入研究并学习这些内容,读者可以加深对栈数据结构和后缀算术表达式的理解,并且能够应用所学知识解决实际问题。
本文不仅适用于计算机科学或相关专业的学生,也适合对数据结构和算法感兴趣的读者阅读和学习。
2. 栈的概念及原理2.1 栈的定义栈是一种具有特定限制条件的线性数据结构,它具备“先进后出”(Last-In-First-Out,LIFO)的特性。
栈可以看作是一个容器,其中可以存储各种类型的数据。
与实际生活中的堆栈类似,栈只允许在其末尾进行插入和删除操作。
在栈中,最后加入的元素首先被访问和处理。
这是由于栈内元素之间的相对位置关系决定的。
插入操作称为“压栈”(Push),删除操作称为“弹栈”(Pop),而从栈顶读取元素或获取栈顶元素但不删除它称为“查看”(Peek)。
2.2 栈的基本操作推入元素:将一个元素添加到栈顶。
如果已经存在满员条件,则无法执行此操作。
弹出元素:从栈顶移除一个元素,并返回移除的值。
如果没有任何元素存在,则无法执行此操作。
查看栈顶元素:获取位于栈顶处的元素值,但不对其进行删除。
判断是否为空:检查栈是否为空。
后缀表达式求值过程嘿,朋友!今天咱们来唠唠后缀表达式求值这个超有趣的事儿。
你可能会想,这后缀表达式是啥呀?就像你看到一个神秘的密码,其实只要掌握了方法,求值就像解开密码锁一样简单又好玩。
我先给你说说啥是后缀表达式吧。
咱平常看到的表达式,像“3 + 4”这种中缀表达式,操作符在中间。
而后缀表达式呢,操作符在操作数的后面,就像“3 4 +”。
这看起来有点怪,可它在计算机处理起来可就方便多啦。
那怎么求值呢?咱得有个小工具,那就是栈。
栈就像一个小盒子,不过这个小盒子有点特别,先放进去的东西后拿出来,就像你往一个窄口瓶子里塞东西,先塞进去的在底下,最后才能拿出来。
比如说咱们要计算“4 5 * 6 +”这个后缀表达式的值。
我和我那聪明的小伙伴小明就开始啦。
小明负责操作栈,我来指挥。
首先看到“4”,小明就把4这个数字放到栈里。
这就像把一个小宝贝放进那个神秘的盒子里。
接着看到“5”,小明也把5放进栈里。
现在栈里就有4和5啦,就像两个小伙伴在盒子里安静地待着。
然后看到“*”这个操作符,这时候就像魔法要开始啦。
小明从栈里拿出5和4(注意哦,是先拿5,因为栈的特性),然后计算4乘以5等于20,再把20放进栈里。
哇,这就像把两个小伙伴融合成了一个超级小伙伴呢!再看到“6”,小明又把6放进栈里。
现在栈里有20和6啦。
最后看到“+”,小明又从栈里拿出6和20,计算20加6等于26,这就是最后的结果啦。
是不是感觉很神奇呢?就像一场奇妙的数学之旅。
再来看一个复杂点的例子吧。
像“3 4 + 2 * 5 -”。
我和我的另一个朋友小花来操作这个。
小花可认真啦。
先看到“3”,放进栈里,再看到“4”,也放进栈里。
看到“+”的时候,小花从栈里拿出4和3,计算3加4等于7,把7放进栈里。
这时候就像我们搭建了一个小积木塔的一部分。
接着看到“2”,放进栈里。
看到“*”的时候,小花从栈里拿出2和7,计算7乘以2等于14,再把14放进栈里。
最后看到“5”,放进栈里,看到“ - ”的时候,小花从栈里拿出5和14,计算14减5等于9。
C#算术表达式求值(后缀法),看这⼀篇就够了⼀、种类介绍算术表达式有三种:前缀表达式、中缀表达式和后缀表达式。
⼀般⽤的是中缀,⽐如1+1,前后缀就是把操作符移到前⾯和后⾯,下⾯简单介绍⼀下这三种表达式。
1、前缀表⽰法前缀表⽰法⼜叫波兰表⽰法,他的操作符置于操作数的前⾯(例:+ 1 2),是波兰数学家扬·武卡谢维奇1920年代引⼊的,⽤于简化命题逻辑。
因为我们⼀般认为操作符是在操作数中间的,所以在⽇常⽣活中⽤的不多,但在计算机科学领域占有⼀席之地。
⼀般的表⽰法对计算机来说处理很⿇烦,每个符号都要考虑优先级,还有括号这种会打乱优先级的存在,将使计算机花费⼤量的资源进⾏解析。
⽽前缀表⽰法没有优先级的概念,他是按顺序处理的。
举个例⼦:9-2*3这个式⼦,计算机需要先分析优先级,先乘后减,找到2*3,再进⾏减操作;化成前缀表⽰法就是:- 9 * 2 3,计算机可以依次读取,操作符作⽤于后⼀个操作数,遇到减就是让9减去后⾯的数,⽽跟着9的是乘,也就是说让9减去乘的结果,这对计算机来说很简单,按顺序来就⾏了。
2、中缀表⽰法这也就是我们⼀般的表⽰法,他的操作符置于操作数的中间(例:1 + 2),前⾯也说过这种⽅法不容易被计算机解析,但他符合⼈们的普遍⽤法,许多编程语⾔也就⽤这种⽅法了。
在中缀表⽰法中括号是必须有的,要不然运算顺序会乱掉。
3、后缀表⽰法后缀表⽰法⼜叫逆波兰表⽰法,他的操作符置于操作数的后⾯(例:1 2 +),他和前缀表⽰法都对计算机⽐较友好,但他很容易⽤堆栈解析,所以在计算机中⽤的很多。
他的解释过程⼀般是:操作数⼊栈;遇到操作符时,操作数出栈,求值,将结果⼊栈;当⼀遍后,栈顶就是表达式的值。
因此逆波兰表达式的求值使⽤堆栈结构很容易实现,且能很快求值。
注意:逆波兰记法并不是简单的波兰表达式的反转。
因为对于不满⾜交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法/ 6 3的逆波兰记法是6 3 /⽽不是3 6 /;数字的数位写法也是常规顺序。
后缀表达式求值实验报告书课程名:数据结构题⽬:后缀表达式求值1、实验题⽬(1)掌握栈“后进先出”的特点。
(2)掌握栈的典型应⽤——后缀表达式求值。
2、实验内容(1)⽤键盘输⼊⼀个整数后缀表达式(操作数的范围是0~9,运算符只含+、—、*、/、,⽽且中间不可以有空格),使⽤循环程序从左向右读⼊表达式。
(2)如果读⼊的是操作数,直接进⼊操作数栈。
(3)如果读⼊的是运算符,⽴即从操作数栈取出所需的操作数,计算操作数运算的值,并将计算结果存回操作数栈。
(4)检验程序运⾏结果。
3、实验要求(1)分析后缀表达式求值的算法思想,⽤C(或C++)语⾳设计程序。
(2)上机调试通过实验程序。
(3)给出具体的算法分析,包括时间复杂度和空间复杂度等。
(4)撰写实验报告(把输⼊实验数据及运⾏结果⽤抓图的形式粘贴到实验报告上)。
(5)本程序运⾏结果通过以后,添加到原教材验证性实验3的菜单中去。
4、实验步骤与源程序错误!未找到引⽤源。
实验步骤使⽤循环从左到右输⼊后缀表达式。
如输⼊的是运算符,⽴即从操作数栈取出两个操作数,计算上述操作数和运算符的值,然后存回操作数栈。
如输⼊的是操作数则直接存⼊操作数栈。
整个过程只需要⼀个操作数栈。
由⼀个链栈结点定义node、push()、pop()、empty()运算函数⼀个main()主函数(完成数据输⼊和函数调⽤)、两个个功能函数:isoperator()//判运算符getvalue()//计算表达式值错误!未找到引⽤源。
源代码#include#includestruct node // 栈结构声明{int data; // 数据域struct node *next; // 指针域typedef struct node stacklist; // 链表新类型typedef stacklist *link; // 链表指新针类型link operand=NULL; // 操作数栈指针void push( int value) // 进栈,存⼊数据{link newnode; // 新结点指针newnode=new stacklist; // 分配新结点if (!newnode){printf("分配失败!"); // 存⼊失败return ;}newnode->data=value; // 创建结点的内容newnode->next=operand;operand=newnode; // 新结点成为栈的开始return ;}void pop(int *value) // 出栈,取出数据{link top; // 指向栈顶if (operand !=NULL){top=operand; // 指向栈顶operand=operand->next; // 移动栈顶指针,指向下⼀个结点*value=top->data; // 取数据delete top; // 吸收结点}else*value=-1;}int empty() // 判栈空{if (operand!=NULL) return 1;else return 0;int isoperator(char op) // 判运算符{switch (op){case'+':case'-':case'*':case'/': return 1; // 是运算符,返回default: return 0; // 不是运算符,返回}}int getvalue(int op,int operand1,int operand2) // 计算表达式值{switch((char)op){case'*': return(operand1*operand2);case'/': return(operand1/operand2);case'+': return(operand1+operand2);case'-': return(operand1-operand2);}}void main() // 主函数{char exp[100];int operand1=0; // 定义操作数int operand2=0; // 定义操作数int result=0; // 定义操作结果变量int pos=0; // ⽬前表达式位置printf("\t\n 请输⼊后缀表达式:");gets(exp); //cin.getline(exp,81) // 读取后缀表达式 printf("\t\n\n 后缀表达式[%s]的结果是:",exp); while (exp[pos] !='\0' && exp[pos] !='\n') // 分析表达式字符串{if (isoperator(exp[pos])) // 是运算符,取两个操作数{pop(&operand2);pop(&operand1);push(getvalue(exp[pos],operand1,operand2)); }elsepush(exp[pos]-48); // 是操作数,压⼊操作数栈 pos++; // 移到下⼀个字符串位置}pop(&result); // 弹出结果printf("%d\n",result); // 输出}5、测试数据与实验结果(可以抓图粘贴)图1:程序运⾏结果6、结果分析与实验体会结果分析:本次实验结果准确。
表达式求值算法表达式求值算法是计算机科学中的重要概念之一,用于计算数学表达式的结果。
在编程语言中,表达式求值是一项基本的操作,并且经常在计算过程中需要用到。
本文将介绍一些常见的表达式求值算法及其实现。
1. 逆波兰表达式法逆波兰表达式法是一种用于计算数学表达式的算法,它使用后缀表达式(也称为逆波兰表达式)来表示表达式。
逆波兰表达式是将操作符放在操作数之后的一种表示方法。
对于任意一个数学表达式,都可以通过将中缀表达式转换为后缀表达式,然后使用栈结构计算得到结果。
逆波兰表达式法的优点是计算顺序明确,不需要考虑运算符的优先级和括号的处理。
2. 中缀表达式转后缀表达式法中缀表达式是我们常见的数学表达式,如 3 + 4 * 5。
在中缀表达式中,操作符的优先级和括号起着很大的作用。
为了将中缀表达式转换为后缀表达式,我们需要使用到栈结构。
具体的算法如下:- 遍历中缀表达式的每个元素。
- 如果是操作数,则直接输出。
- 如果是操作符,则判断其与栈顶操作符的优先级,决定是否将其压入栈。
- 如果是左括号,则直接压入栈。
- 如果是右括号,则依次弹出栈顶操作符,并输出,直到遇到左括号为止。
- 遍历完表达式后,如果栈不为空,则依次弹出栈顶操作符,并输出。
3. 后缀表达式求值法后缀表达式(逆波兰表达式)的求值方法相对简单。
我们可以使用栈结构来计算后缀表达式的结果。
具体的算法如下:- 遍历后缀表达式的每个元素。
- 如果是操作数,则将其压入栈。
- 如果是操作符,则弹出栈顶的两个操作数,执行相应的计算,并将结果压入栈。
- 遍历完后缀表达式后,栈中最后剩下的元素即为计算结果。
4. 二叉树表示法除了逆波兰表达式法和中缀表达式法,我们还可以使用二叉树来表示表达式,并通过遍历二叉树来计算表达式的结果。
具体的算法如下:- 构建二叉树,将表达式的操作符作为根节点,将操作数作为叶节点。
- 通过后序遍历二叉树,计算出每个子树的值,并将结果返回给其父节点。
c语言基于二叉树的表达式求值算法C语言中,基于二叉树的表达式求值算法主要包括两部分:中缀表达式转换为后缀表达式和后缀表达式求值。
1.中缀表达式转换为后缀表达式中缀表达式是我们常见的数学表达方式,例如3 + 4 * 2 - 5。
为了方便计算机求值,我们需要将中缀表达式转换为后缀表达式,也叫做逆波兰表达式。
转换的过程使用栈数据结构来实现。
具体算法如下:1.定义一个栈和一个结果字符串,栈用于存储操作符,结果字符串用于保存后缀表达式。
2.从左到右遍历中缀表达式的每一个字符。
3.如果当前字符是数字,直接将其加入结果字符串。
4.如果当前字符是左括号"(",将其入栈。
5.如果当前字符是右括号")",则依次将栈顶的操作符弹出并加入结果字符串,直到遇到左括号为止,同时将左括号从栈中弹出。
6.如果当前字符是操作符,需要将栈中优先级比当前操作符高或者相等的操作符弹出并加入结果字符串,然后将当前操作符入栈。
7.遍历完所有字符后,将栈中剩余的操作符依次弹出并加入结果字符串。
8.最终结果字符串就是后缀表达式。
例如,对于中缀表达式3 + 4 * 2 - 5,转换为后缀表达式为3 4 2 * + 5 -2.后缀表达式求值后缀表达式求值算法使用栈数据结构来实现。
具体算法如下:1.定义一个栈,用于存储操作数。
2.从左到右遍历后缀表达式的每一个字符。
3.如果当前字符是数字,则将其转换为对应的整数并入栈。
4.如果当前字符是操作符,则从栈中弹出两个操作数,先弹出的作为右操作数,后弹出的作为左操作数,根据操作符进行运算,得到结果后入栈。
5.遍历完所有字符后,栈顶的数字即为最终的结果。
例如,对于后缀表达式3 4 2 * + 5 -,求值的过程如下:1.入栈3。
2.入栈4。
3.入栈2。
4.弹出2和4,计算4 * 2 = 8,将8入栈。
5.弹出8和3,计算3 + 8 = 11,将11入栈。
6.入栈5。
7.弹出5和11,计算11 - 5 = 6,得到最终结果。
实验报告书
课程名:数据结构
题目:后缀表达式求值
1、实验题目
(1)掌握栈“后进先出”的特点。
(2)掌握栈的典型应用——后缀表达式求值。
2、实验内容
(1)用键盘输入一个整数后缀表达式(操作数的范围是0~9,运算符只含+、—、*、/、,而且中间不可以有空格),使用循环程序从左向右读入表达式。
(2)如果读入的是操作数,直接进入操作数栈。
(3)如果读入的是运算符,立即从操作数栈取出所需的操作数,计算操作数运算的值,并将计算结果存回操作数栈。
(4)检验程序运行结果。
3、实验要求
(1)分析后缀表达式求值的算法思想,用C(或C++)语音设计程序。
(2)上机调试通过实验程序。
(3)给出具体的算法分析,包括时间复杂度和空间复杂度等。
(4)撰写实验报告(把输入实验数据及运行结果用抓图的形式粘贴到实验报告上)。
(5)本程序运行结果通过以后,添加到原教材验证性实验3的菜单中去。
4、实验步骤与源程序
错误!未找到引用源。
实验步骤
使用循环从左到右输入后缀表达式。
如输入的是运算符,立即从操作数栈取出两个操作数,计算上述操作数和运算符的值,然后存回操作数栈。
如输入的是操作数则直接存入操作数栈。
整个过程只需要一个操作数栈。
由一个链栈结点定义node、push()、pop()、empty()运算函数一个main()主函数(完成数据输入和函数调用)、
两个个功能函数:
isoperator()//判运算符
getvalue()//计算表达式值
错误!未找到引用源。
源代码
#include<stdlib.h>
#include<stdio.h>
struct node // 栈结构声明
{
int data; // 数据域
struct node *next; // 指针域
};
typedef struct node stacklist; // 链表新类型
typedef stacklist *link; // 链表指新针类型
link operand=NULL; // 操作数栈指针
void push( int value) // 进栈,存入数据
{
link newnode; // 新结点指针
newnode=new stacklist; // 分配新结点
if (!newnode)
{
printf("分配失败!"); // 存入失败
return ;
}
newnode->data=value; // 创建结点的内容
newnode->next=operand;
operand=newnode; // 新结点成为栈的开始
return ;
}
void pop(int *value) // 出栈,取出数据
{
link top; // 指向栈顶
if (operand !=NULL)
{
top=operand; // 指向栈顶
operand=operand->next; // 移动栈顶指针,指向下一个结点
*value=top->data; // 取数据
delete top; // 吸收结点
}
else
*value=-1;
}
int empty() // 判栈空
{
if (operand!=NULL) return 1;
else return 0;
}
int isoperator(char op) // 判运算符
{
switch (op)
{
case'+':
case'-':
case'*':
case'/': return 1; // 是运算符,返回
default: return 0; // 不是运算符,返回
}
}
int getvalue(int op,int operand1,int operand2) // 计算表达式值
{
switch((char)op)
{
case'*': return(operand1*operand2);
case'/': return(operand1/operand2);
case'+': return(operand1+operand2);
case'-': return(operand1-operand2);
}
}
void main() // 主函数
{
char exp[100];
int operand1=0; // 定义操作数
int operand2=0; // 定义操作数
int result=0; // 定义操作结果变量
int pos=0; // 目前表达式位置
printf("\t\n 请输入后缀表达式:");
gets(exp); //cin.getline(exp,81) // 读取后缀表达式 printf("\t\n\n 后缀表达式[%s]的结果是:",exp);
while (exp[pos] !='\0' && exp[pos] !='\n') // 分析表达式字符串
{
if (isoperator(exp[pos])) // 是运算符,取两个操作数
{
pop(&operand2);
pop(&operand1);
push(getvalue(exp[pos],operand1,operand2)); }
else
push(exp[pos]-48); // 是操作数,压入操作数栈 pos++; // 移到下一个字符串位置
}
pop(&result); // 弹出结果
printf("%d\n",result); // 输出
}
5、测试数据与实验结果(可以抓图粘贴)
图1:程序运行结果
6、结果分析与实验体会
结果分析:
本次实验结果准确。
按照题目要求得出结果了。
算法分析:
设后缀表达式长度为n,
程序中的栈运算时间复杂度都为:O(1);
功能函数的时间复杂度也都为:O(1)
主函数复杂度都是为:O(n);
所以总时间复杂度都是为:O(n);
总空间复杂度都是为:O(n);
实验体会:
通过了运用课堂所学的知识以及课外的相关知识学习,我掌握了在顺序栈和链栈上实现进栈、出栈、读栈顶元素、判栈空和判栈满等基本操作。
栈是限制在表尾进行插入和删除操作的线性表。
体会到栈的逻辑结构和线性表相同,其主要特性是“后进先出”;熟悉了栈在计算机的软件设计中的各种应用,能灵活应用栈的基本原理解决一些综合性的应用问题。
不过在运行中间出现了点错误,经过思考和与同学的商量完成了这次的设计,在学习的过程中我觉得一定要多看书本和翻阅课外资料才能够学好数据结构这门课程。