栈的应用表达式求值的设计

合集下载

C++实例(表达式求值(栈的应用))

C++实例(表达式求值(栈的应用))

表达式求值: 设计⼀个程序实现输⼊⼀个表达式如3*(3+4),以”#”结尾,求出其值。

分析: 先分析⼀下四则运算的规则: 1. 先乘除后加减; 2. 从左到右计算; 3. 先括号内后括号外; 于是我们要把运算符的优先级确定清楚。

这⾥我只⽤这⼏个运算符:+-*/(), 可以知道+-的优先级低于*/,⽽对于(),当第⼀次遇到’(‘时,’(‘后⾯的就优先计算,直到遇到’)’为⽌,可以先把’(’的优先级定为⽐其它⼏个都⾼,然后遇到’)’时把⾥⾯的先算出来,再算括号外⾯的,具体实现在代码中会表现得很清楚。

考试2⼤提⽰这个程序还是⽤栈来实现,具体代码如下。

代码: #include #include using namespace std; const int STACK_INIT_SIZE=100; //The maximize length of stack template class Stack //A class of stack { public: Stack() //Constructor function { base = new int[STACK_INIT_SIZE]; if (!base) { cerr< exit(-1); } top=base; stacksize=STACK_INIT_SIZE; } ~Stack() //Destructor function { if (base) delete[] base; } T GetTop() { if (top==base) { cerr< exit(-1); } return *(top-1); } void Push(T e) { if (top-base>=stacksize) { base=new int[STACK_INIT_SIZE]; if(!base) { cerr< exit(-1); } top=base+STACK_INIT_SIZE; stacksize+=STACK_INIT_SIZE; } *top++=e; } void Pop(T& e) { if (top==base) { cerr< exit(-1); } e=*--top; } private: int *base; int *top; int stacksize; }; string op("+-*/()#"); //The set of operator bool In(char c,string op) //Judge the character whether belong to the set of operator { string::iterator iter=op.begin(); for (;iter!=op.end();++iter) if (*iter==c) return true; return false; } char Precede(char top,char c) //Confirm the precedence of operator { int grade_top=0,grade_c=0; switch (top) { case '#':grade_top=0;break; case ')':grade_top=1;break; case '+':grade_top=2;break; case '-':grade_top=2;break; case '*':grade_top=3;break; case '/':grade_top=3;break; case '(':grade_top=4;break; } switch (c) { case '#':grade_c=0;break; case ')':grade_c=1;break; case '+':grade_c=2;break; case '-':grade_c=2;break; case '*':grade_c=3;break; case '/':grade_c=3;break; case '(':grade_c=4;break; } if (grade_top>=grade_c) { if (top=='('&&c!=')') return ' else if (top=='('&&c==')') return '='; return '>'; } else if (top=='#'&&c=='#') return '='; else return ' } int Operate(int a,char theta,int b) //Calculate { if (theta=='+') return a+b; else if (theta=='-') return a-b; else if (theta=='*') return a*b; else if (theta=='/') return a/b; return 0; } int EvaluateExpression(Stack& OPTR,Stack& OPND) { int a=0,b=0,n=0; char x; char theta; string c; cin>>c; OPTR.Push('#'); while (c[0]!='#'||OPTR.GetTop()!='#') { if (!In(c[0],op)){ n=atoi(&c[0]); OPND.Push(n); cin>>c; } else switch (Precede(OPTR.GetTop(),c[0])) { case ' OPTR.Push(c[0]); cin>>c; break; case '=': OPTR.Pop(x); cin>>c; break; case '>': OPTR.Pop(theta); OPND.Pop(b); OPND.Pop(a); OPND.Push(Operate(a,theta,b)); break; } } return OPND.GetTop(); } int main() { Stack OPTR; Stack OPND; cout< cout< return 0; }。

堆栈的定义及应用

堆栈的定义及应用

堆栈的定义及应用堆栈(Stack)是一种数据结构,它按照后进先出(LIFO)的原则存储数据。

也就是说,最后存入堆栈的数据元素最先被取出,而最先存入的数据元素最后被取出。

堆栈中包含两个主要操作:压栈(Push)和弹栈(Pop)。

压栈是指将数据元素存入堆栈,弹栈是指从堆栈中取出数据元素。

除此之外,还有一个查看栈顶元素的操作。

堆栈的实际应用非常广泛,以下列举几个常见的应用场景:1. 函数调用与递归:在程序中,每当一个函数被调用,系统将会为这个函数分配一段内存空间,这段内存空间就被称为函数的栈帧。

当函数执行完毕后,栈帧会被销毁。

函数调用过程中,每次调用都会将返回地址和相关参数等信息压入栈中,在函数执行完毕后再将这些信息弹出。

递归函数的实现也离不开堆栈,每次递归调用都会生成一个新的栈帧,直到递归结束后才开始回溯弹栈。

2. 表达式求值:在编程语言中,堆栈可以用于实现算术表达式求值。

例如,中缀表达式需要通过堆栈进行转换成后缀表达式来简化计算过程,然后再通过堆栈进行后缀表达式的计算。

在进行表达式求值时,通过堆栈可以保存运算符和操作数的顺序,确保运算的优先级正确。

3. 括号匹配:在编程或者数学等领域,括号匹配是一个常见的问题。

我们可以使用堆栈来判断一个表达式中的括号是否匹配。

遍历表达式,每当遇到左括号时,将其压入堆栈。

当遇到右括号时,从堆栈中弹出一个左括号,若左右括号匹配,则继续遍历。

若右括号没有对应的左括号或者堆栈为空,则括号不匹配。

4. 浏览器的历史记录:在浏览器中,通过点击链接或者前进后退按钮,我们可以在不同的网页之间进行切换。

这种网页切换也可以使用堆栈来实现浏览历史记录的功能。

每当访问一个新网页时,将其URL压入堆栈顶部;当点击前进按钮时,从堆栈中弹出一个URL;当点击后退按钮时,将当前页面的URL压入堆栈,然后再弹出上一个URL。

5. 撤销与恢复:在许多软件中,都提供了撤销与恢复功能。

当用户对文档进行操作时,软件会将操作信息(如添加、删除、修改等)压入堆栈中,当用户点击撤销时,软件会从堆栈中弹出最近的操作信息并进行撤销操作;当用户点击恢复时,软件会从堆栈中弹出已经撤销的操作信息并进行恢复。

数据结构实验三栈和队列的应用

数据结构实验三栈和队列的应用

数据结构实验三栈和队列的应用数据结构实验三:栈和队列的应用在计算机科学领域中,数据结构是组织和存储数据的重要方式,而栈和队列作为两种常见的数据结构,具有广泛的应用场景。

本次实验旨在深入探讨栈和队列在实际问题中的应用,加深对它们特性和操作的理解。

一、栈的应用栈是一种“后进先出”(Last In First Out,LIFO)的数据结构。

这意味着最后进入栈的元素将首先被取出。

1、表达式求值在算术表达式的求值过程中,栈发挥着重要作用。

例如,对于表达式“2 + 3 4”,我们可以通过将操作数压入栈,操作符按照优先级进行处理,实现表达式的正确求值。

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

最终,操作数栈中的唯一值就是表达式的结果。

2、括号匹配在程序代码中,检查括号是否匹配是常见的任务。

可以使用栈来实现。

遍历输入的字符串,当遇到左括号时,将其压入栈;当遇到右括号时,弹出栈顶元素,如果弹出的左括号与当前右括号类型匹配,则继续,否则表示括号不匹配。

3、函数调用和递归在程序执行过程中,函数的调用和递归都依赖于栈。

当调用一个函数时,当前的执行环境(包括局部变量、返回地址等)被压入栈中。

当函数返回时,从栈中弹出之前保存的环境,继续之前的执行。

递归函数的执行也是通过栈来实现的,每次递归调用都会在栈中保存当前的状态,直到递归结束,依次从栈中恢复状态。

二、队列的应用队列是一种“先进先出”(First In First Out,FIFO)的数据结构。

1、排队系统在现实生活中的各种排队场景,如银行排队、餐厅叫号等,可以用队列来模拟。

新到达的顾客加入队列尾部,服务完成的顾客从队列头部离开。

通过这种方式,保证了先来的顾客先得到服务,体现了公平性。

2、广度优先搜索在图的遍历算法中,广度优先搜索(BreadthFirst Search,BFS)常使用队列。

从起始节点开始,将其放入队列。

栈的应用教学设计

栈的应用教学设计

出”。

四、栈的应用举例任何一个表达式都是由操作数、运算符和界限符组成的。

后两项统称为算符,算符集合命名为OP。

引入问题:如何用堆栈实现表达式求值?表达式求值有三种形式。

中缀表示:<操作数><运算符><操作数>前缀表示:<运算符><操作数><操作数>后缀表示:<操作数><操作数><运算符>以中缀表达式为例,进行重点讲解。

例2、用栈求解表达式21+44-3*6的值。

# 21+44-3*6#实现方法:设置一个运算符栈和一个操作数栈。

算符间的优先关系求值规则:1)先乘除,后加减;2)先括号内,后括号外;3)同类运算,从左至右。

约定:q1---栈顶的运算符q2---当前的运算符当q1=#,为开始符当q2=#,为结束符根据上述优先关系表,可见21+44-3*6#中‘-’ <‘*’,‘*’ >‘#’。

2、算法基本思想1)首先置‘#’为运算符栈的栈底元素, 操作数栈为空栈;2) 依次读入表达式中各个字符,如果判断为操作数则OPND栈,如21,44,进操作数栈;若为运算符θ2,则和OPTR的栈顶元素θ1比较优先级,θ1和θ2进行比较。

当θ1 < θ2 ,θ2 进栈;表达式21+44-3*6的算法编程实现。

[动画演示]1.5分钟结合算法演示系统,讲解用栈求解表达式21+44-3*6的算法执行过程。

[小结]2分钟栈的定义,栈的“先进后出”的特性;栈的顺序存储的实现;栈的应用。

当θ1 = θ2 ,θ1 出栈;若θ1 > θ2 ,θ1 出栈,先进行操作数求值;然后运算结果再进栈。

3、算法编程实现OperandType EvaluateExpression ( ){ InitStack(OPTR);push(OPTR,`#`);InitStack(OPND);read(w);Whi le NOT ((w=’#’)AND (GetTop(OPTR)= `#`) )[IF w NOT IN op THEN[ push(OPND,w); read(w);ELSE CASEPrecede(GetTop(OPTR),w)OF`<`:[ push(OPTR,c); read(w);]`=`: [pop(OPTR,x);if x=FUNCTION thenPUSH(OPND,x(POP(OPNE)));read(w);]`>`: [b:= pop(OPND);a:= pop(OPND);theta:= pop(OPTR);push(OPND,Operate(a,theta,b));]ENDC; ]RETURN(POP(OPND))ENDF;4、算法执行过程# 21+44-3*6#1)“#”先压入到运算符栈,即push(OPTR,`#`);OPTR OPND2)push(OPND,`21`)2)‘#’ <‘+’,push(OPTR, `+` );3)push(OPND,`44`)。

实验二--栈的应用---算术表达式的计算

实验二--栈的应用---算术表达式的计算

浙江大学城市学院实验报告课程名称数据结构与算法实验项目名称实验二栈的应用---算术表达式的计算实验成绩指导老师(签名)日期一.实验目的和要求1.进一步掌握栈的基本操作的实现。

2.掌握栈在算术表达式的计算方面的应用。

二. 实验内容1. 编写程序利用栈将中缀表达式转换成后缀表达式,即从键盘输入任一个中缀表达式(字符串形式),转换成后缀表达式后,将后缀表达式输出。

假设:中缀表达式包含圆括号( ) 及双目运算符+、-、*、/、^(乘方)。

要求:把栈的基本操作的实现函数存放在头文件stack1.h中(栈元素的类型为char),在主文件test6_2.cpp中包含将中缀表达式S1转换成后缀表达式S2的转换函数void Change( char *S1, char *S2 )及主函数,在主函数中进行输入输出及转换函数的调用。

2. 选做:编写利用栈对后缀表达式进行求值的函数double Compute(char *str),以计算从前述程序得到的后缀表达式的值。

要求:把栈的基本操作的实现函数存放在头文件stack2.h中(栈元素的类型为double),在主文件test6_2.cpp中添加后缀表达式求值函数,并在主函数中增加调用求值函数及输出结果值的语句。

3. 填写实验报告,实验报告文件取名为report2.doc。

4. 上传实验报告文件report2.doc与源程序文件stack1.h、stack2.h(若有)及test6_2.cpp到Ftp服务器上你自己的文件夹下。

二.函数的功能说明及算法思路(算法思路见源程序的注释部分)//栈的顺序存储结构定义struct Stack{ElemType *stack;int top;int MaxSize;};//初始化栈S为空void InitStack(Stack &S)//元素item进栈,即插入到栈顶void Push(Stack &S,ElemType item)//删除栈顶元素并返回ElemType Pop(Stack &S)//读取栈顶元素的值ElemType Peek(Stack &S)//判断S是否为空,若是则返回true,否则返回false bool EmptyStack(Stack &S)//清除栈S中的所有元素,释放动态存储空间void ClearStack(Stack &S)//将中缀算术表达式转换为后缀算术表达式void Change(char *S1,char *&S2)//返回运算符op所对应的优先级数值int Precedence(char op)//计算由str所指字符串的后缀表达式的值double Compute(char *str)四. 实验结果与分析五. 心得体会【附录----源程序】test6_2.cpp#include<iostream.h>#include<stdlib.h>#include<math.h>#include"stack1.h"#include"stack2.h"void main(){char x[30],y[30];double r;while(1){cout<<"请输入一个中缀算术表达式:";cin.getline(x,sizeof(x));Change(x,y);cout<<"对应的后缀算术表达式为:";cout<<y<<endl;r=Compute(y);cout<<"后缀算术表达式值为:"<<r<<endl<<endl;}}stack1.htypedef char ElemType1;struct Stack1{ElemType1 *stack;int top;int MaxSize;};void InitStack(Stack1 &S){S.MaxSize=10;S.stack=new ElemType1[S.MaxSize];if(!S.stack){cerr<<"动态储存分配失败"<<endl;exit(1);}S.top=-1;}void Push(Stack1 &S,ElemType1 item)if(S.top==S.MaxSize-1){int k=sizeof(ElemType1);S.stack=(ElemType1*)realloc(S.stack,2*S.MaxSize*k);S.MaxSize=2*S.MaxSize;}S.top++;S.stack[S.top]=item;}ElemType1 Pop(Stack1 &S){if(S.top==-1){cerr<<"Stack is empty! "<<endl;exit(1);}S.top--;return S.stack[S.top+1];}ElemType1 Peek(Stack1 &S){if(S.top==-1){cerr<<"Stack is empty! "<<endl;exit(1);}return S.stack[S.top];}bool EmptyStack(Stack1 &S){return S.top==-1;}void ClearStack(Stack1 &S){if(S.stack){delete []S.stack;S.stack=0;}S.top=-1;S.MaxSize=0;}//返回运算符op所对应的优先级数值int Precedence(char op){switch(op){case'+':case'-':return 1;case'*':case'/':return 2;case'^':return 3;case'(':case'@':default:return 0;}}//将中缀算术表达式转换为后缀算术表达式void Change(char *S1,char *S2){Stack1 R;InitStack(R);Push(R,'@');int i=0,j=0;char ch=S1[i];while(ch!='\0'){//对于空格字符不做任何处理,顺序读取下一个字符if(ch==' ')ch=S1[++i];//对于左括号,直接进栈else if(ch=='('){Push(R,ch);ch=S1[++i];}//对于右括号,使括号内的仍停留在栈中的运算符依次出栈并写入S2else if(ch==')'){while(Peek(R)!='(')S2[j++]=Pop(R);Pop(R);//删除栈顶的左括号ch=S1[++i];}//对于运算符,使暂存于栈顶且不低于ch优先级的运算符依次出栈并写入S2else if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='^'){char w=Peek(R);while(Precedence(w)>=Precedence(ch)){S2[j++]=w;Pop(R);w=Peek(R);}Push(R,ch);//把ch运算符写入栈中ch=S1[++i];}else{if((ch<'0'||ch>'9')&&ch!='.'){cout<<"中缀表达式表示错误!"<<endl;exit(1);}while((ch>='0'&&ch<='9')||ch=='.'){S2[j++]=ch;ch=S1[++i];}S2[j++]=' ';}}//把暂存在栈中的运算符依次退栈并写入到S2中ch=Pop(R);while(ch!='@'){if(ch=='('){cerr<<"expression error!"<<endl;exit(1);}else{S2[j++]=ch;ch=Pop(R);}}S2[j++]='\0';}stack2.htypedef double ElemType2;struct Stack2{ElemType2 *stack;int top;int MaxSize;};void InitStack(Stack2 &S){S.MaxSize=10;S.stack=new ElemType2[S.MaxSize];if(!S.stack){cerr<<"动态储存分配失败"<<endl;exit(1);}S.top=-1;}void Push(Stack2 &S,ElemType2 item){if(S.top==S.MaxSize-1){int k=sizeof(ElemType2);S.stack=(ElemType2*)realloc(S.stack,2*S.MaxSize*k);S.MaxSize=2*S.MaxSize;}S.top++;S.stack[S.top]=item;}ElemType2 Pop(Stack2 &S){if(S.top==-1){cerr<<"Stack is empty! "<<endl;exit(1);}S.top--;return S.stack[S.top+1];}ElemType2 Peek(Stack2 &S){if(S.top==-1){cerr<<"Stack is empty! "<<endl;exit(1);}return S.stack[S.top];}bool EmptyStack(Stack2 &S){return S.top==-1;}void ClearStack(Stack2 &S){if(S.stack){delete []S.stack;S.stack=0;}S.top=-1;S.MaxSize=0;}//计算由str所指字符串的后缀表达式的值double Compute(char *str){Stack2 S;InitStack(S);double x,y;int i=0;while(str[i]){if(str[i]==' '){i++;continue;}switch(str[i]){case '+':x=Pop(S)+Pop(S);i++;break;case'-':x=Pop(S);x=Pop(S)-x;i++;break;case'*':x=Pop(S)*Pop(S);i++;break;case'/':x=Pop(S);if(x!=0)x=Pop(S)/x;else{cerr<<"Divide by 0!"<<endl;exit(1);}i++;break;case'^':x=Pop(S);x=pow(Pop(S),x);i++;break;default:x=0;while(str[i]>=48&&str[i]<=57){x=x*10+str[i]-48;i++;}if(str[i]=='.'){i++;y=0;double j=10.0;while(str[i]>=48&&str[i]<=57){y=y+(str[i]-48)/j;i++;j*=10;}x+=y;}}Push(S,x);}if(EmptyStack(S)){cerr<<"expression error!"<<endl;exit(1);}x=Pop(S);if(EmptyStack(S))return x;else{cerr<<"expression error!"<<endl;exit(1);}ClearStack(S);}(注:可编辑下载,若有不当之处,请指正,谢谢!)。

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

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

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

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

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

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

一、算法思路首先,我们需要明确一个重要概念——逆波兰表达式(ReversePolish notation)。

逆波兰表达式是一种没有括号的算术表达式,其运算规则是先计算后面的数字和运算符,再计算前面的数字和运算符。

例如,对于算术表达式“3+4*5-6”,其对应的逆波兰表达式为“3 45 * +6 -”。

那么,我们可以利用栈来实现将中缀表达式转化为逆波兰表达式的过程,具体步骤如下:1. 创建两个栈——操作数栈和操作符栈。

2. 从左到右扫描中缀表达式的每一个数字和运算符,遇到数字则压入操作数栈中,遇到运算符则进行如下操作:(1)如果操作符栈为空或当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符压入操作符栈中。

(2)如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符弹出并加入操作数栈中,重复此过程直到遇到优先级较低的运算符或操作符栈为空为止,然后将当前运算符压入操作符栈中。

3. 扫描完中缀表达式后,若操作符栈不为空,则将其中所有运算符弹出并加入操作数栈中。

4. 最终,操作数栈中存放的就是逆波兰表达式,我们可以按照逆波兰表达式的计算规则来计算其结果。

二、算法优点利用栈来实现算术表达式求值的算法具有以下优点:1. 代码简洁易懂,易于实现和维护。

2. 由于将中缀表达式转化为逆波兰表达式后,可以减少运算符的优先级关系而消除括号,从而减少求值的复杂度,提高程序的执行效率。

三、代码实现下面是利用栈来实现算术表达式求值的算法的Python代码实现:```pythonclass Stack:def __init__(self):self.items = []def push(self, item):self.items.append(item)def pop(self):return self.items.pop()def peek(self):return self.items[-1]def is_empty(self):return len(self.items) == 0def size(self):return len(self.items)def calculate(op_num1, op_num2, operator):if operator == "+":return op_num1 + op_num2elif operator == "-":return op_num1 - op_num2elif operator == "*":return op_num1 * op_num2elif operator == "/":return op_num1 / op_num2def infix_to_postfix(infix_expr):opstack = Stack()postfix_expr = []prec = {"+": 1, "-": 1, "*": 2, "/": 2, "(": 0} token_list = infix_expr.split()for token in token_list:if token.isdigit():postfix_expr.append(token)elif token == '(':opstack.push(token)elif token == ')':top_token = opstack.pop()while top_token != '(':postfix_expr.append(top_token)top_token = opstack.pop()else:while (not opstack.is_empty()) and(prec[opstack.peek()] >= prec[token]):postfix_expr.append(opstack.pop())opstack.push(token)while not opstack.is_empty():postfix_expr.append(opstack.pop())return " ".join(postfix_expr)def postfix_eval(postfix_expr):opstack = Stack()token_list = postfix_expr.split()for token in token_list:if token.isdigit():opstack.push(int(token))else:op_num2 = opstack.pop()op_num1 = opstack.pop()result = calculate(op_num1, op_num2, token) opstack.push(result)return opstack.pop()infix_expr = "3 + 4 * 5 - 6"postfix_expr = infix_to_postfix(infix_expr)print(postfix_expr)print(postfix_eval(postfix_expr))```四、总结算术表达式求值是一项常见的数学运算任务,利用栈这一数据结构来实现求值算法是一种简单有效的方法,它将中缀表达式转化为逆波兰表达式后,可以消除括号并减少运算符的优先级关系,从而提高程序的执行效率。

数据结构实验报告栈

数据结构实验报告栈

数据结构实验报告:栈摘要:本实验报告旨在介绍栈这一重要的数据结构,以及在实际应用中的使用。

栈是一种先进后出(LIFO)的数据结构,在计算机科学中有着广泛的应用。

本报告将详细介绍栈的定义、基本操作以及应用实例,并根据实验结果进行分析和总结。

1. 引言栈是一种基于线性表的数据结构,具有后进先出(LIFO)的特性。

它可以通过两个基本操作来实现:push(入栈)将元素添加到栈顶,pop(出栈)将栈顶元素移除。

栈在计算机科学中被广泛应用,如函数调用、表达式求值、括号匹配等。

2. 栈的实现栈可以通过数组或链表来实现。

数组实现的栈称为顺序栈,链表实现的栈称为链式栈。

无论是哪种实现方式,都需要实现以下基本操作:- push(element): 将元素添加到栈顶。

- pop(): 移除栈顶元素并返回。

- top(): 返回栈顶元素的值。

- isEmpty(): 判断栈是否为空。

- isFull(): 判断栈是否已满(仅顺序栈需要实现)。

3. 栈的应用3.1 函数调用栈在函数调用中起着关键作用。

每当一个函数被调用时,当前函数的局部变量、返回地址等信息都会被压入栈中。

当函数执行完毕时,这些信息会从栈中弹出,继续执行上一级函数。

3.2 表达式求值栈常用于表达式求值,特别是中缀表达式的转换和计算。

通过将中缀表达式转换为后缀表达式,可以方便地进行计算。

栈可以临时存储运算符,并根据运算符的优先级进行弹出和计算。

3.3 括号匹配栈的一个重要应用是括号匹配。

通过遍历字符串,将左括号压入栈中。

每当遇到右括号时,如果栈顶元素是匹配的左括号,则弹出栈顶元素;否则,表示括号不匹配。

4. 实验结果与分析根据我们对栈的实现和应用进行的实验,以下是我们得到的结论:- 通过数组实现的顺序栈在空间上存在一定的限制,可能会出现栈溢出的情况。

- 通过链表实现的链式栈没有空间限制,可以动态地添加和删除元素。

- 栈在函数调用和表达式求值中展现出了高效的性能,并能够简化程序的设计。

栈的应用及特性

栈的应用及特性

栈的应用及特性栈是计算机科学中一种非常重要的数据结构,具有广泛的应用和独特的特性。

下面将详细介绍栈的应用及特性。

一、栈的应用:1. 函数调用:在程序执行过程中,函数的调用和返回通常采用栈进行管理。

当一个函数被调用时,函数的参数和局部变量被压入栈中,函数执行完毕后,这些信息会被弹出栈恢复到调用函数的状态。

2. 表达式求值:在编程语言中,栈可用于表达式求值、中缀表达式转换为后缀表达式等相关操作。

通过利用栈的先进后出特性,可以方便地实现这些功能。

3. 递归算法:递归算法中的递归调用也可以通过栈来实现。

当算法需要递归调用时,将函数和相关变量的信息压入栈中,等到递归结束后,再从栈中弹出恢复状态。

4. 括号匹配:栈也常用于判断表达式中的括号是否匹配。

遍历表达式,遇到左括号时压入栈,遇到右括号时弹出栈顶元素,如果匹配则继续,不匹配则判定为括号不匹配。

5. 浏览器的前进后退:浏览器的前进后退功能可以使用栈实现。

每次浏览一个网页时,将该网页的URL压入栈中,点击后退按钮时,再从栈中弹出上一个URL,即可实现返回上一个网页的功能。

6. 撤销操作:在图形界面软件中,通常会有撤销操作。

使用栈可以将每一步操作的状态依次压入栈中,当用户需要撤销时,再从栈中弹出最近的状态,恢复到之前的操作状态。

二、栈的特性:1. 先进后出:栈是一种后进先出(LIFO)的数据结构,即最新添加的元素最先被访问或者删除。

这一特性使得栈能够方便地实现函数调用和返回等操作。

2. 只能操作栈顶元素:由于栈的特性,只能访问或者修改栈顶元素,无法直接访问或者修改栈中的其他元素。

需要先将栈顶元素弹出后,才能访问或者修改下一个栈顶元素。

3. 顺序存储结构:栈可以使用数组或者链表实现。

使用数组实现时,需要指定栈的最大容量,而使用链表实现时,没有容量限制。

4. 操作复杂度:栈的插入和删除操作只涉及栈顶元素,所以其操作复杂度为O(1)。

但是栈的搜索和访问操作需要从栈顶开始遍历,所以其操作复杂度为O(n)。

栈的运用实验报告

栈的运用实验报告

一、实验目的1. 理解栈的基本概念、特点及逻辑结构;2. 掌握栈的顺序存储和链式存储结构;3. 熟练掌握栈的基本操作,如入栈、出栈、判断栈空等;4. 理解栈在递归算法中的应用;5. 探究栈在实际问题中的应用。

二、实验内容1. 栈的定义与特点2. 栈的顺序存储结构3. 栈的链式存储结构4. 栈的基本操作5. 栈在递归算法中的应用6. 栈在实际问题中的应用三、实验步骤1. 栈的定义与特点(1)栈是一种后进先出(LIFO)的数据结构;(2)栈的元素只能从一端(栈顶)进行插入和删除操作;(3)栈具有两个基本操作:入栈和出栈。

2. 栈的顺序存储结构(1)使用数组来实现栈的顺序存储结构;(2)定义一个数组作为栈的存储空间;(3)定义栈顶指针top,初始值为-1;(4)定义栈的最大容量maxSize。

3. 栈的链式存储结构(1)使用链表来实现栈的链式存储结构;(2)定义一个链表节点,包含数据域和指针域;(3)定义栈顶指针top,初始时指向链表头节点。

4. 栈的基本操作(1)入栈操作:将元素插入到栈顶,栈顶指针向上移动;(2)出栈操作:删除栈顶元素,栈顶指针向下移动;(3)判断栈空:判断栈顶指针是否为-1,是则栈空,否则栈非空。

5. 栈在递归算法中的应用(1)斐波那契数列的递归算法;(2)汉诺塔问题;(3)迷宫问题。

6. 栈在实际问题中的应用(1)括号匹配问题;(2)表达式求值问题;(3)递归函数的调用栈。

四、实验结果与分析1. 栈的定义与特点通过本次实验,我们深入理解了栈的基本概念、特点及逻辑结构,掌握了栈的后进先出特性。

2. 栈的顺序存储结构使用数组实现栈的顺序存储结构,操作简单高效。

在实验过程中,我们实现了栈的基本操作,如入栈、出栈、判断栈空等。

3. 栈的链式存储结构使用链表实现栈的链式存储结构,具有灵活性和扩展性。

在实验过程中,我们实现了栈的基本操作,如入栈、出栈、判断栈空等。

4. 栈的基本操作通过实验,我们熟练掌握了栈的基本操作,如入栈、出栈、判断栈空等,为后续递归算法和实际问题中的应用奠定了基础。

栈的应用实验报告

栈的应用实验报告

栈的应用实验报告导言:在计算机科学领域中,数据结构是一项非常重要的基础。

栈是一种常用的数据结构,它在算法设计和软件开发中具有广泛的应用。

本实验旨在探索栈的应用,并通过实际操作来加深对栈数据结构的理解。

实验目的:1. 了解栈的定义和基本操作。

2. 掌握栈在实际问题中的应用方法。

3. 培养问题分析和解决的能力。

实验步骤:1. 实现栈的基本操作:压入(push)和弹出(pop)。

2. 针对以下实际问题,设计并实现相应的栈应用。

一、括号匹配问题括号匹配问题是指在一个字符串中,括号的开闭配对是否正确。

例如,"{[()]}"是正确的括号匹配,而"{[(])}"则是错误的括号配对。

通过使用栈,我们可以很方便地解决这个问题。

算法步骤如下:1. 遍历字符串的每个字符。

2. 若字符是左括号,则将其压入栈中。

3. 若字符是右括号,则检查栈是否为空,若为空则配对错误;若非空,则弹出栈顶元素并检查是否与右括号匹配。

4. 遍历结束后,若栈为空,则括号匹配正确,否则匹配错误。

二、函数调用问题在计算机程序中,函数的调用和返回遵循"先进后出"的原则,即后调用的函数先返回。

栈提供了一种便捷的方式来管理函数调用和返回过程。

在实际的编程中,我们可以使用栈来存储函数的局部变量和返回地址等信息。

例如,以下是一个简单的函数调用示例:1. 函数A调用函数B。

2. 函数B在栈中保存局部变量和返回地址。

3. 函数B执行完毕后,从栈中弹出局部变量和返回地址,程序继续执行函数A。

三、逆波兰表达式求值问题逆波兰表达式是一种不使用括号来表示表达式的方法,而是通过运算符放置在操作数之后的方式来表示。

例如,表达式"2 3 +"等价于中缀表达式"2 + 3"。

利用栈,我们可以很方便地对逆波兰表达式进行求值。

算法步骤如下:1. 遍历逆波兰表达式的每个元素。

2. 若元素是操作数,则将其压入栈中。

栈的应用——表达式求值

栈的应用——表达式求值

栈的应⽤——表达式求值 表达式求值是程序设计语⾔编译中的⼀个基本问题,它的实现就是对“栈”的典型应⽤。

本⽂针对表达式求值使⽤的是最简单直观的算法“算符优先法”。

本⽂给出两种⽅式来实现表达式求值,⽅式⼀直接利⽤中缀表达式求值,需要⽤到两个栈,操作数栈和操作符栈。

⾸先置操作数栈为空栈,操作符栈仅有“#”⼀个元素。

依次读⼊表达式中的每个字符,若是操作数则进操作数栈,若是操作符则和操作符栈的栈顶运算符⽐较优先权作相应操作,直⾄整个表达式求值完毕。

⽅式⼆⾸先把中缀表达式转换为后缀表达式并存储起来,然后利⽤读出的后缀表达式完成求值,其本质上是⽅式⼀的分解过程。

表达式求值的代码如下:#include <iostream>#include "stack"#include "map"using namespace std;/* 只能求⼀位整数的加减乘除混合运算 */map<char, pair<int, int>> priority; // 存放各个操作符的栈内栈外优先级,first是栈内,second是栈外char infix[50]; // 存放初始的中缀表达式char postfix[50]; // 存放转化的后缀表达式int result;void MakePriority() // 构造运算符优先级表{priority.insert(make_pair('#', make_pair(0, 0))); // isp(#)=0, icp(#)=0priority.insert(make_pair('\n', make_pair(0, 0))); // isp(\n)=0, icp(\n)=0 表达式结尾的'#'⽤'\n'代替,这样可以省略表达式末尾的结束符'#'priority.insert(make_pair('(', make_pair(1, 6))); // isp(()=1, icp(()=6priority.insert(make_pair('*', make_pair(5, 4))); // isp(*)=5, icp(*)=4priority.insert(make_pair('/', make_pair(5, 4))); // isp(/)=5, icp(/)=4priority.insert(make_pair('%', make_pair(5, 4))); // isp(%)=5, icp(%)=4priority.insert(make_pair('+', make_pair(3, 2))); // isp(+)=3, icp(+)=2priority.insert(make_pair('-', make_pair(3, 2))); // isp(-)=3, icp(-)=2priority.insert(make_pair(')', make_pair(6, 1))); // isp())=6, icp())=1}void InfixToPostfix() // 把中缀表达式转换为后缀表达式{int i = 0;stack<char> optrStack; // 操作符栈char optr; // optr为栈顶的操作符optrStack.push('#');while (!optrStack.empty()){if (isdigit(infix[i])) // 是操作数则直接输出(追加到postfix结尾){postfix[strlen(postfix)] = infix[i];postfix[strlen(postfix) + 1] = '\0';i++; // 读⼊中缀表达式的下⼀个字符}else// 是操作符, ⽐较优先级{optr = optrStack.top(); // 取出栈顶操作符if (priority[infix[i]].second > priority[optr].first) // icp(infix[i]) > isp(optr),infix[i]⼊栈{optrStack.push(infix[i]);i++;}else if (priority[infix[i]].second < priority[optr].first)// icp(infix[i]) < isp(optr),optr退栈并输出{postfix[strlen(postfix)] = optr;postfix[strlen(postfix) + 1] = '\0';optrStack.pop();}else// icp(infix[i]) = isp(optr),退栈但不输出,若退出的是'(',则继续读⼊下⼀个字符{optrStack.pop();if (optr == '(')i++;}}}}void CalculateByPostfix() // 通过后缀表达式求值{int i = 0;stack<int> opndStack; // 操作数栈int left, right; // 左右操作数int value; // 中间结果int newOpnd;while (postfix[i] != '#' && i < strlen(postfix)){switch (postfix[i]){case'+':right = opndStack.top(); // 从操作数栈中取出两个操作数opndStack.pop();left = opndStack.top();opndStack.pop();value = left + right;opndStack.push(value); // 中间结果⼊栈break;case'-':right = opndStack.top();opndStack.pop();left = opndStack.top();opndStack.pop();value = left - right;opndStack.push(value);break;case'*':right = opndStack.top();opndStack.pop();left = opndStack.top();opndStack.pop();value = left * right;opndStack.push(value);break;case'/':right = opndStack.top();opndStack.pop();left = opndStack.top();opndStack.pop();if (right == 0){cerr << "Divide by 0!" << endl;}else{value = left / right;opndStack.push(value);}break;default:newOpnd = (int)(postfix[i] - 48); // 操作数直接⼊栈opndStack.push(newOpnd);break;}i++;}result = opndStack.top();}void CalculateByInfix() // 直接利⽤中缀表达式求值{int i = 0;stack<char> optrStack; // 操作符栈stack<int> opndStack; // 操作数栈char optr; // optr为操作符栈顶的操作符int left, right, value; // 左右操作数以及中间结果optrStack.push('#');optr = optrStack.top();while (!optrStack.empty()) // 直到操作符栈为空{if (isdigit(infix[i])) // 是操作数, 进操作数栈{value = (int)(infix[i] - 48);opndStack.push(value);i++;}else// 是操作符, ⽐较优先级{optr = optrStack.top(); // 取出操作符栈顶的操作符if (priority[infix[i]].second > priority[optr].first) // icp(infix[i]) > isp(optr),infix[i]⼊栈 {optrStack.push(infix[i]);i++;}else if (priority[infix[i]].second < priority[optr].first) // icp(infix[i]) < isp(optr),optr退栈并输出{optrStack.pop();right = opndStack.top(); // 从操作数栈中取出两个操作数opndStack.pop();left = opndStack.top();opndStack.pop();switch (optr){case'+':value = left + right;opndStack.push(value); // 中间结果⼊栈break;case'-':value = left - right;opndStack.push(value); // 中间结果⼊栈break;case'*':value = left * right;opndStack.push(value); // 中间结果⼊栈break;case'/':if (right == 0){cerr << "Divide by 0!" << endl;}else{value = left / right;opndStack.push(value);}break;default:break;}}else{optrStack.pop();if (optr == '(')i++;}}}result = opndStack.top();}int main(){MakePriority(); // 构造运算符优先级表cout << "请输⼊中缀表达式:";cin >> infix;cout << "直接利⽤中缀表达式求值为:";CalculateByInfix();cout << result << endl;cout << "转化为后缀表达式:";InfixToPostfix();for (int i = 0;i < strlen(postfix);i++){cout << postfix[i];}cout << endl;cout << "利⽤后缀表达式求值为:";CalculateByPostfix();cout << result << endl;return0;} 为了⽅便起见,本⽂只是简单的设计了⼀个针对⼀位整数的四则运算进⾏求值的算法,对于处理多位整数的四则运算,需要对本⽂接受输⼊的数据类型进⾏“升阶”,把字符数组换成字符串数组,将⼀个整数的多位数字存⼊⼀个字符串进⾏处理。

用栈解决表达式求值问题的c语言代码

用栈解决表达式求值问题的c语言代码

栈是一种常见的数据结构,用于解决许多算法和数据处理问题。

在编程中,栈通常用于处理表达式求值问题。

本篇文章将介绍如何使用栈解决表达式求值问题,并给出对应的C语言代码。

1. 表达式求值问题介绍表达式求值是指计算一个数学表达式的值,通常涉及到四则运算、括号和优先级等概念。

给定一个表达式“3 + 4 * 2”,我们需要得到其计算结果为11。

在编程中,需要将该表达式转换为计算机可识别的形式,并使用算法进行求值。

2. 中缀表达式、前缀表达式和后缀表达式在计算机中常见的表达式有三种形式:中缀表达式、前缀表达式和后缀表达式。

其中,中缀表达式是通常人们在日常生活中使用的表达式形式,如“3 + 4 * 2”。

前缀表达式是运算符位于操作数之前的形式,例如“+ 3 * 4 2”。

后缀表达式则是运算符位于操作数之后的形式,例如“3 4 2 * +”。

3. 使用栈解决表达式求值问题在解决表达式求值问题时,我们可以利用栈的特性来简化计算过程。

具体步骤如下:3.1 将中缀表达式转换为后缀表达式我们需要将中缀表达式转换为后缀表达式,这样可以简化表达式的计算顺序。

具体转换规则如下:- 从左至右扫描中缀表达式的每个数字或符号。

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

- 如果是运算符,则弹出栈中所有优先级大于或等于该运算符的运算符,并将其压入栈中,然后压入该运算符。

- 如果是括号,则根据括号的不同情况进行处理。

通过以上规则,我们可以将中缀表达式转换为后缀表达式。

3.2 计算后缀表达式的值得到后缀表达式后,我们可以利用栈来计算其值。

具体步骤如下:- 从左至右扫描后缀表达式的每个数字或符号。

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

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

- 继续扫描直到表达式结束,栈中的值即为所求结果。

通过以上步骤,我们可以使用栈来解决表达式求值问题。

4. C语言代码实现以下是使用C语言实现栈来解决表达式求值问题的代码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct {int top;int capacity;int* array;} Stack;Stack* createStack(int capacity) {Stack* stack = (Stack*)malloc(sizeof(Stack));stack->capacity = capacity;stack->top = -1;stack->array = (int*)malloc(stack->capacity * sizeof(int)); return stack;}int isFull(Stack* stack) {return stack->top == stack->capacity - 1; }int isEmpty(Stack* stack) {return stack->top == -1;}void push(Stack* stack, int item) {if (isFull(stack)) return;stack->array[++stack->top] = item;}int pop(Stack* stack) {if (isEmpty(stack)) return -1;return stack->array[stack->top--];}int evaluatePostfix(char* exp) {Stack* stack = createStack(strlen(exp)); for (int i = 0; exp[i]; i++) {if (isdigit(exp[i])) {push(stack, exp[i] - '0');} else {int val1 = pop(stack);int val2 = pop(stack);switch (exp[i]) {case '+':push(stack, val2 + val1); break;case '-':push(stack, val2 - val1); break;case '*':push(stack, val2 * val1); break;case '/':push(stack, val2 / val1); break;}}}return pop(stack);}int m本人n() {char exp[] = "34*2+";printf("The value of s is d\n", exp, evaluatePostfix(exp));return 0;}```以上代码实现了栈的基本功能,并利用栈来计算后缀表达式的值。

数据结构试验:栈和队列实验——表达式求值

数据结构试验:栈和队列实验——表达式求值

实验报告课程名称数据结构实验项目实验二--栈和队列实验系别___ _计算机学院 _ ______专业___ _计算机科学与技术___班级/学号__学生姓名 ____________实验日期成绩_______________________指导教师实验题目:实验二-----栈和队列实验一、实验目的1)掌握栈的顺序存储结构及队列的链式存储结构;2)验证栈的顺序存储结构的操作的实现;3)验证队列的链式存储结构的操作的实现;4)理解算法与程序的关系,能够将算法转换为对应程序。

二、实验内容1)建立一个顺序存储的空栈,并以此分别实现入栈、出栈、取栈顶元素;2)建立一个链式结构的空队列,并以此分别实现入队、出队、取队头等基本操作;3)尝试利用栈和队列的算法解决一些实际的应用问题。

设计与编码1)实验题目主要需求说明2)设计型题目:表达式求值(要求利用栈结构和运算符优先约定表,输入一个表达式,并计算求值)3)结合题目,说明利用栈或队列解决问题的基本算法描述4)程序源码#include<iostream>using namespace std;const int InitSize=100;const int IncreastSize=10;template<class datatype>class SqStack {private:datatype *base;datatype *top;int stacksize;public:SqStack();void DestroyStack();void ClearStack();int StackLength();bool IsEmpty();bool GetTop(datatype &e);bool Pop(datatype &e);bool Push(datatype e);};template<class datatype>SqStack<datatype>::SqStack(){base=new datatype[InitSize];if(!base)exit(1);top=base;stacksize=InitSize;}template<class datatype>void SqStack<datatype>::DestroyStack() {delete[] base;base=top=NULL;stacksize=0;}template<class datatype>void SqStack<datatype>::ClearStack() {top=base;}template<class datatype>int SqStack<datatype>::StackLength() {return top-base;}template<class datatype>bool SqStack<datatype>::IsEmpty() {if(top==base)return fasle;else return true;}template<class datatype>bool SqStack<datatype>::GetTop(datatype &e){if(top==base)return false;e=*(top-1);return true;}template<class datatype>bool SqStack<datatype>::Pop(datatype &e){if(top==base)return false;e=*(top-1);top--;return true;}template<class datatype>bool SqStack<datatype>::Push(datatype e){if(top-base>=stacksize){base=(datatype *)realloc( base , (stacksize+IncreastSize)*sizeof(int) ); if(!base)exit(1);top=base+stacksize;stacksize+=IncreastSize;}*(top)=e;top++;return true;}int com(char m,char t){if(t=='(') return -1;else if(t==')'){if(m=='+'||m=='-'||m=='*'||m=='/') return 1; else if(m=='(') return 0;else return -2;}else if(t=='*'||t=='/'){if(m=='+'||m=='-'||m=='#'||m=='(') return -1; else return 1;}else if(t=='+'||t=='-'){if(m=='#'||m=='(') return -1;else return 1;}else{if(m=='#')return 0;else if(m=='+'||m=='-'||m=='*'||m=='/') return 1; else return -2;}}void main(){SqStack <char> op;SqStack <double> re;char t,m;double result,flag=1;op.Push('#');t=getchar();while(true){if(t>='0'&&t<='9'){double s=0;s=s*10+t-'0';t=getchar();while(t>='0'&&t<='9' ){s=s*10+t-'0';t=getchar();}re.Push(s);}else if(t=='+'||t=='-'||t=='*'||t=='/'||t=='('||t==')'||t=='\n') { op.GetTop(m);while(com(m,t)==1 ){double x1,x2;op.Pop(m);if(re.Pop(x2)&&re.Pop(x1)){if(m=='+') re.Push(x1+x2);else if(m=='-') re.Push(x1-x2);else if(m=='*') re.Push(x1*x2);else if(m=='/') {if(x2!=0)re.Push(x1/x2); else flag=0;} }else flag=0;op.GetTop(m);}if(com(m,t)==-1)op.Push(t);else if(com(m,t)==0)op.Pop(m);else flag=0;if(!op.GetTop(m)) break;t=getchar();}else t=getchar();}if(re.GetTop(result)&&flag)cout<<result<<endl;else cout<<"Input error!\n";}5)运行结果三、总结与心得。

栈的应用表达式求值的原理

栈的应用表达式求值的原理

栈的应用:表达式求值的原理一、栈的基本原理1.栈是一种具有特殊操作的线性数据结构。

2.栈的特点是后进先出(LIFO,Last In First Out)的存取方式。

3.栈有两个基本操作:入栈和出栈。

二、表达式求值的概念1.表达式是由运算符和运算对象组成的序列。

2.表达式求值是指根据运算符的优先级和结合性来计算表达式的值。

三、中缀表达式与后缀表达式1.中缀表达式:运算符位于运算对象的中间。

–例如:2 + 32.后缀表达式(逆波兰表达式):运算符位于运算对象的后面。

–例如:2 3 +四、中缀转后缀表达式1.利用栈实现中缀表达式到后缀表达式的转换。

2.遍历中缀表达式中的每个字符,若为数字,则输出到后缀表达式中;若为运算符,则根据优先级进行处理。

3.将运算符入栈,直到出现低优先级的运算符或左括号。

4.遇到右括号时,将栈中的运算符出栈并输出,直到遇到左括号。

5.将剩余的运算符出栈并输出。

五、后缀表达式求值1.利用栈实现后缀表达式的求值。

2.遍历后缀表达式中的每个字符,若为数字,则入栈;若为运算符,则弹出栈中的两个数字进行计算,并将结果入栈。

3.最后栈中的唯一元素即为表达式的求值结果。

六、示例假设要求解的中缀表达式为:2 + 3 * 4 - 5 1. 将中缀表达式转换为后缀表达式:2 3 4 * + 5 - 2. 根据后缀表达式求值的原则,遍历后缀表达式进行计算: - 遇到数字2,入栈; - 遇到数字3,入栈; - 遇到运算符*,弹出栈中的两个数字3和2进行计算得到6,并将结果入栈; - 遇到运算符+,弹出栈中的两个数字6和4进行计算得到10,并将结果入栈; - 遇到数字5,入栈; - 遇到运算符-,弹出栈中的两个数字10和5进行计算得到5,并将结果入栈。

3. 栈中的唯一元素5即为表达式的求值结果。

七、总结1.栈的应用在表达式求值中起到关键作用。

2.利用栈可以将中缀表达式转换为后缀表达式,并通过对后缀表达式的求值获得最终结果。

栈的应用实验报告

栈的应用实验报告

栈的应用实验报告栈的应用实验报告引言:栈是一种常见的数据结构,它具有后进先出(Last In First Out,LIFO)的特点。

在计算机科学中,栈被广泛应用于各种领域,如编译器、操作系统、图形处理等。

本实验旨在通过实际应用场景,探索栈的应用。

一、栈的基本概念和操作栈是一种线性数据结构,它由一系列元素组成,每个元素都有一个前驱元素和一个后继元素。

栈的基本操作包括入栈(Push)和出栈(Pop)。

入栈将元素添加到栈的顶部,而出栈则将栈顶元素移除。

此外,栈还具有查看栈顶元素(Top)和判断栈是否为空(IsEmpty)的操作。

二、栈在表达式求值中的应用栈在表达式求值中发挥着重要作用。

例如,当我们需要计算一个数学表达式时,可以通过将表达式转换为后缀表达式,并利用栈来进行求值。

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

通过这种方式,我们可以实现高效的表达式求值。

三、栈在函数调用中的应用栈在函数调用中也扮演着重要角色。

当我们调用一个函数时,计算机会将函数的返回地址、参数和局部变量等信息存储在栈中。

这样,当函数执行完毕后,可以从栈中恢复之前的上下文,继续执行调用函数的代码。

栈的这种特性使得递归函数的实现成为可能,同时也为程序的模块化提供了便利。

四、栈在迷宫求解中的应用栈在迷宫求解中也能发挥重要作用。

当我们需要找到从起点到终点的路径时,可以利用栈来存储当前路径上的位置。

从起点开始,我们按照某种策略选择下一个位置,并将其入栈。

如果当前位置无法继续前进,则将其出栈,并选择下一个位置。

通过不断重复这个过程,直到找到终点或者栈为空,我们就能得到迷宫的解。

五、栈在撤销和恢复操作中的应用栈在撤销和恢复操作中也能发挥重要作用。

当我们在编辑文档或者绘图时,经常需要进行撤销和恢复操作。

栈可以用来记录每次操作的状态,当用户选择撤销时,从栈中弹出最近的操作,并将文档或图形恢复到之前的状态。

通过这种方式,我们可以提供良好的用户体验,同时也方便用户进行操作的回溯。

带括号的四则运算表达式的求值(栈实现)

带括号的四则运算表达式的求值(栈实现)

带括号的四则运算表达式的求值(栈实现)利用栈这种数据结构来实现一个加减乘除以及带括弧的混合数学表达式的计算,对于数学表达式的计算,可以设置一个运算符栈和一个数字栈,分别来保存运算符、数字或者中间计算得到的结果。

将整个表达式看做一个字符串,从开头依次判断每个字符是运算符还是数字,若是运算符,则根据运算符优先级来确定是将其压栈还是弹栈进行计算;若是数字,则先将其转化并计入一个临时double型变量中,看下一个字符是否为运算符栈,若是,则将临时变量压进数字栈,否则读取下一个数字字符并进行相关处理后累加到临时变量中,直到下一个字符为运算符,将临时变量压进数字栈。

最后,当字符为"="时,结束计算,得到计算结果。

本算法需要先设置一个运算符优先级表,下表可供参考:参考代码如下:注:本代码输入表达式时末尾不需要“=”,程序中会自动添加#include <cstdio>#include <cstdlib>#include <cmath>#include <stack>#include <cstring>using namespace std;char Precede(char a, char b) { //判断运算符优先级int i, j;char Table[8][8] = {{' ','+','-','*','/','(',')','='},{'+','>','>','<','<','<','>','>'},{'-','>','>','<','<','<','>','>'},{'*','>','>','>','>','<','>','>'},{'/','>','>','>','>','<','>','>'},{'(','<','<','<','<','<','=',' '},{')','>','>','>','>',' ','>','>'},{'=','<','<','<','<','<',' ','='}}; //优先级表格for(i=0; i<8; i++)if(Table[0][i]==a) //寻找运算符abreak;for(j=0; j<8; j++) //寻找运算符bif(Table[j][0]==b)break;return Table[j][i];}bool Calcu_temp(double a, char theta, double b, double &r) { //计算二元表达式的值if(theta=='+')r = a + b;else if(theta=='-')r = a - b;else if(theta=='*')r = a * b;else {if(fabs(b-0.0)<1e-8) //如果除数为0,返回错误信息return false;elser = a / b;}return true;}bool IsOper(char ch) { //判断字符ch是否为运算符char ptr[10] = {'+', '-', '*', '/', '(', ')', '='};int i;for(i=0; i<7; i++) {if(ch==ptr[i])return true;}return false;}bool Calculate(char s[], double &result) { //计算表达式的结果char theta;int i = 0, j, point = 0;double a, b, r, num = 0;stack<double> num_stack; //数字栈stack<char> oper_stack; //运算符栈oper_stack.push('=');while(s[i]!='=' || oper_stack.top()!='=') { //对表达式a进行计算if((s[i]>='0' && s[i]<='9') || s[i]=='.') { //字符是数字或者小数点num = 0; //初始化数字为0point = 0; //point用来标记是否出现小数点以及当前处于小数点后第x位,point==10^xif(s[i]=='.')point = 10;elsenum = s[i] - 48;j = i + 1;while(!IsOper(s[j])) { //继续往后查找并记录该数字,直到该数字结束遇到运算符为止if(s[j]=='.') {point = 10;j++;continue;}if(!point) //整数部分num = num * 10 + ( s[j] - 48 );else {num = num + 1.0 * ( s[j] - 48 ) / point; //小数部分point *= 10; //小数位数后移一位}j++;}i = j;num_stack.push(num); //将该数字压入栈中}else if(IsOper(s[i])) { //字符是运算符switch(Precede(s[i],oper_stack.top())) { //该运算符和栈顶运算符进行优先级比较并做相关处理case '<':oper_stack.push(s[i++]);break;oper_stack.pop();i++;break;case '>':theta = oper_stack.top(); //从栈中弹出一个运算符进行计算oper_stack.pop();b = num_stack.top(); //弹出两个数字,注意顺序,先弹出的数是第二个操作数num_stack.pop();a = num_stack.top();num_stack.pop();if ( Calcu_temp(a, theta, b, r) ) //计算并判断是否有除数等于0的情况num_stack.push(r); //若正常,则将结果压入栈中elsereturn false; //出现除数为0的情况,返回错误信息break;}}}result = num_stack.top(); //最后数字栈中的数即为表达式的最终结果return true;}bool Check(char s[]) { //检查表达式括号是否匹配int flag=0, i;for(i=0; s[i]!=0; i++) {if(s[i]=='(')if(s[i]==')')flag--;}if(flag)return false;elsereturn true;}int main() {// freopen("in.txt", "r", stdin);int i, j;char s1[210], s2[210];double result;while(gets(s1)!=NULL) { //输入表达式if(strlen(s1)==1 && s1[0]=='0')break;for(i=0,j=0; s1[i]!=0; i++) { //将表达式转换为规格化的表达式,并在末尾加上“=”,保存在s2中if(s1[i]==' ')continue;s2[j++] = s1[i];}s2[j++] = '=';s2[j] = '\0';if(Check(s2)) { //检查括号是否匹配if(Calculate(s2, result)) //计算并检查表达式中是否出现除数为0的情况printf("%lf\n",result);elseprintf("The divisor cannot be zero!\n");}elseprintf("The parentheses do not match!\n");}return 0;}/*in.txt:1 +2 / (3 - 2.2 / 1.10 ) + 54 + 2.03 * .05 - 7 / 3.52 + 3. - .11 +2 / ( 2 - 2.2 / 1.1 ) - 32 * ( (3 + 2 ) - 3*/本代码生成的程序,在输入表达式时,数字与运算符之间可以有若干空格或者没有;对于小数,可以没有整数部分(即小数点之前没有数字),也可以没有小数部分(即小数点之后没有数字);表达式可以为无效表达式(如括号不匹配或者出现除数为0的情况等);如以上的样例输入。

栈的相关操作及应用

栈的相关操作及应用

栈的相关操作及应用栈是一种具有特殊结构的线性数据结构,它的特点是只能在一端进行操作。

这一端被称为栈顶,另一端被称为栈底。

栈的基本操作包括入栈操作(Push)和出栈操作(Pop)。

入栈操作指的是将数据元素插入到栈顶的位置,同时栈顶指针向上移动一位。

出栈操作指的是将栈顶元素删除,并将栈顶指针向下移动一位。

栈还具有一个基本操作——取栈顶元素(Peek),它可以返回栈顶元素的值而不删除它。

栈的应用非常广泛,下面我将介绍一些常见的应用场景。

1. 括号匹配问题:在编程中,经常需要判断一段代码中的括号是否匹配。

这时可以使用栈来解决。

遍历整个代码,遇到左括号就入栈,遇到右括号时判断栈顶元素是否为对应的左括号,如果是,则出栈,继续遍历;如果不是,则括号不匹配。

最后判断栈是否为空,如果为空,则所有括号都匹配。

2. 函数调用栈:在程序执行过程中,每次调用函数时都会将当前函数的局部变量、函数参数等保存在栈中。

当函数返回时,栈顶元素出栈,程序回到之前的函数继续执行。

这样可以实现程序对函数执行过程的跟踪和管理。

3. 表达式求值:在计算机科学中,中缀表达式(如:3 + 4 * 5)通常不方便计算机直接求值,而将中缀表达式转换为后缀表达式(也称为逆波兰表达式)则可以方便计算机求值。

这个转换的过程可以使用栈来实现。

遍历中缀表达式,遇到操作数直接输出,遇到运算符则与栈顶运算符进行比较,如果优先级高于栈顶运算符,则入栈,如果低于或等于栈顶运算符,则将栈顶运算符出栈直到遇到优先级低于它的运算符,然后将当前运算符入栈。

最后将栈中剩余的运算符依次出栈输出。

4. 浏览器的前进和后退:浏览器的前进和后退功能可以使用两个栈来实现。

一个栈用于保存浏览的历史记录,每当用户点击链接或提交表单时,将当前页面的URL入栈。

另一个栈用于保存前进的页面,当用户点击后退按钮时,将历史记录栈顶元素出栈并入栈到前进栈中,然后将前进栈顶元素出栈并跳转到该页面。

5. 编译器的语法分析:编译器在进行语法分析时通常会使用到栈。

3.3.2栈的应用教学设计

3.3.2栈的应用教学设计
3.随堂测试:教师设计一些与本节课相关的编程题目,让学生在课堂上进行测试。通过测试结果,了解学生对栈的基本操作、应用场景等的理解和掌握程度。
4.课后作业:教师对学生的课后作业进行批改和评价,了解学生对栈的应用的掌握程度和应用能力。
5.教师评价与反馈:教师根据以上评价结果,对学生进行综合评价,指出学生的优点和不足,并提出改进建议。同时,教师应鼓励学生积极思考,提出问题,提高学生的学习兴趣和主动性。
教学资源准备
1.教材:确保每位学生都有本节课所需的教材,如《高中信息技术》课本及相关学习资料,以便学生能够跟随教学进度进行学习和复习。
2.辅助材料:准备与教学内容相关的图片、图表、案例等多媒体资源,以便在教学过程中进行直观展示和解释,帮助学生更好地理解和掌握栈的应用。
3.实验器材:本节课可能需要涉及一些编程实践,因此需要准备计算机、编程环境等实验器材,确保实验器材的完整性和安全性,以便学生能够进行实际操作和练习。
(二)存在主要问题
1.教学管理:课堂纪律管理不够严格,部分学生上课注意力不集中。
2.教学方法:教学方法过于单一,缺乏与学生的互动和反馈。
3.教学评价:评价方式过于注重结果,忽视了学生的学习过程和能力培养。
(三)改进措施
1.加强课堂纪律管理,严格要求学生遵守课堂纪律,提高课堂效果。
2.采用多样化的教学方法,如提问、讨论、小组合作等,增加与学生的互动和反馈,提高学生的参与度。
对于对课程学习有积极影响的学生,我们可以设计更具挑战性的教学活动,如编程竞赛、实际项目开发等,以提高他们的学习兴趣和能力。对于对课程学习有困难的学生,我们需要关注他们的学习过程,提供更多的辅导和帮助,鼓励他们积极参与课堂讨论和实践活动,提高他们的学习兴趣和能力。同时,我们还需要关注学生的学习态度和行为习惯,引导他们树立正确的学习观念,培养良好的学习习惯。

栈的应用实验报告 -回复

栈的应用实验报告 -回复

栈的应用实验报告-回复首先,我们来了解栈是什么?栈是一种常见的数据结构,它具有特定的操作规则。

栈的特点是后进先出(Last In First Out, LIFO),即最后进入栈的元素首先被访问。

栈的应用非常广泛,涉及到各个领域,例如计算机科学、编程、算法等等。

在本次实验中,我们将探讨栈的一些典型应用。

第一部分:基础概念及实现首先,我们需要了解栈的基本概念。

栈由两个主要操作组成:入栈(push)和出栈(pop)。

入栈操作将元素放入栈顶,出栈操作则将栈顶元素移除。

栈还有一个很重要的操作,即查看栈顶元素(peek),它可以让我们获取栈顶的数值而不移除它。

除此之外,栈还有一个判断是否为空的操作(isEmpty)。

在实现栈的数据结构时,最常见的方式是使用数组或链表。

数组实现的栈具有固定大小,而链表实现的栈则可以动态增长。

无论使用哪种方式,栈的基本操作都是一样的。

第二部分:栈的应用1.表达式求值表达式求值是栈的一个重要应用。

当我们要对一个复杂的数学表达式求值时,可以使用栈来实现。

我们可以使用两个栈来辅助计算,一个栈用来存储运算符,另一个栈用来存储操作数。

根据运算符的优先级,来决定入栈顺序和出栈顺序,最后得到表达式的结果。

2.括号匹配在编程中,经常会遇到括号匹配的情况。

例如,在编写一个函数或条件语句时,需要保证括号的匹配是正确的。

通过使用栈,我们可以轻松实现括号的匹配检查。

当遇到左括号时,将其入栈;当遇到右括号时,将栈顶元素出栈。

如果经过遍历整个字符串后,栈为空,则说明括号匹配正确。

3.函数调用在计算机程序的执行过程中,函数的调用是通过栈来实现的。

当我们调用一个函数时,将当前函数的状态(如返回地址、局部变量等)压入栈中。

当函数执行完毕后,再将这些状态从栈中弹出,以恢复到上一个函数的执行状态。

4.逆波兰表达式逆波兰表达式是将运算符放在操作数之后的一种表达式形式。

通过使用栈可以很方便地计算逆波兰表达式。

当遇到一个数字时,将其入栈;当遇到一个运算符时,从栈中弹出相应数量的操作数进行计算,然后将计算结果再次入栈。

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

数据结构课程设计报告栈的应用:表达式求值专业计算机科学与技术学生姓名班级学号指导教师完成日期2014年7月4日表达式求值的设计目录1设计内容 (1)2设计分析 (1)2.1后缀表达式设计 (1)2.2 中缀到后缀的转换设计 (2)3设计实践 (3)3.1实现要求 (3)3.2程序代码 (3)4测试方法 (17)4.1测试目的 (17)4.2 测试输入 (17)4.3 正确输出 (18)4.4 实际输出 (18)5程序运行效果 (18)6设计心得 (19)栈的应用:表达式求值的设计1设计内容设计一个表达式求值的程序。

该程序必须可以接受包含(,),+,-,*,/,%,和^(求幂运算符,a^b=a b)的中缀表达式,并求出结果。

如果表达式正确,则输出表达式的结果;如果表达式非法,则输出错误信息。

输入要求:程序从“input.txt”文件中读取信息,在这个文件中如果有多个中缀表达式,则每个表达式独占一行,程序的读取操作在文件在文件的结尾处停止。

输出要求:对于每个表达式,将其结果放在“output.txt”文件的每一行中。

这些结果可能是值,也可能是错误信息“ERROR IN INFIX NOTATION”。

2 设计分析在计算机中,算术表达式的计算往往是通过使用栈来实现的。

所以,本表达式求值程序的最主要的数据结构就是栈。

可以使用栈来存储输入表达式的操作符和操作数。

输入的表达式是由操作数(又称运算对象)和运算符以及改变运算次序的圆括号连接而成的式子。

算术表达式有中缀表示法和后缀表示法,本程序输入的表达式采用中缀表示法,在这种表达式中,二元运算符位于两个操作数中间。

由于不同运算符之间存在优先级,同一优先级的运算间又存在着运算结合顺序的问题,所以简单的从左到右的计算是不充分的。

当然凭直观判断一个中缀表达式中哪个运算符最先,哪个次之,哪个最后并不困难,但通过计算机处理就比较困难了。

因为计算机只能一个字符一个字符地扫描,要想知道哪个运算符先算,就必须对整个中缀表达式扫描一遍。

而后缀表达式则很容易通过应用栈实现表达式的计算,这为实现表达式求值程序提供了一种直接的计算机制。

2.1后缀表达式设计后缀表达式是由一系列的运算符、操作数组成的表达式,其中运算符位于两个操作数之后。

后缀表达式很容易通过应用栈实现表达式的计算。

其基本过程是:当输入一个操作数时,它被压入栈中,当一个运算符出现时,就从栈中弹出适当数量的操作数,对该运算进行计算,计算结果再压回栈中。

对于最常见的二元运算符来说,弹出的操作数只有两个。

处理完整个后缀表达式之后,栈顶上的元素就是表达式的结果值。

整个计算过程不需要理解计算的优先级规则。

2.2 中缀到后缀的转换设计从上面的分析可知,后缀表达式是很容易应用栈进行计算的,但要处理的是中缀表达式。

同样,也可以应用栈将中缀表达式转换为后缀表达式。

此时,栈里要保存的是运算符,而在后缀表达式计算中,栈里保存的是操作数。

应用栈将中缀表达式转换为后缀表达式的基本过程如下。

从头到尾读取中缀表达式的每个对象,对不同对象按不同的情况处理:●如果遇到空格,则认为是分隔符,不需处理。

●若遇到操作数,则直接输出。

●若是左括号,则将其压入至栈中。

●若遇到的是右括号,表明括号的中缀表达式已经扫描完毕,把括号中的运算符退栈,并输出。

●若遇到的是运算符,当该运算符的优先级大于栈顶运算符的优先级时,则把它压栈,当该运算符的优先级小于等于栈顶运算符时,将栈顶运算符退栈并输出,再比较新的栈顶运算符,按同样处理方法,直到该运算符大于栈顶运算符优先级为止,然后将该运算符压栈。

●若中缀表达式处理完毕,则要把栈中存留的运算符一并输出。

上述处理过程的一个关键是不同运算符优先级的设置。

在程序实现中,可以用一个数来代表运算符的优先级,优先级数值越大,它的优先级越高,这样的优先级的比较就转换为两个数的大小比较。

程序的整体算法过程分两步:第一步,从“input.txt”文件中读取中缀表达式,并应用运算符栈OpHolder 把中缀表达式转换为后缀表达式,将输出结果(转换后得到的后缀表达式)存放在一个temp文件中。

第二步,从temp文件中读取后缀表达式,并应用操作数栈Operands计算后缀表达式结果,将结果输出到“output.txt”文件中。

本程序中的栈采用前面所述的带头节点的链式存储结构,涉及两种类型:用于存储运算符号的char类型的链栈以及用于存储操作数的float类型的链栈。

本程序将整个求值过程分解为两个步骤:中缀表达式转换为后缀表达式、计算后缀表达式结果值。

其实,可以将这两个过程统一合并在一起完成,当然也同样需要操作数和运算符这两类栈。

另外,本程序中,应用函数OperatorValue来判别运算符的优先级,一种更灵活的方式是应用数组来记录各运算符的优先级。

读者可应用以上思路对本程序进一步改进。

3设计实践3.1实现要求本程序的输入形式是“input.txt”文件,输出结果存放到“output.txt”文件中。

在输入文件中等式的格式必须是中缀格式,例如1+2*3,而且每一行只允许一个表达式。

本程序将读入的中缀表达式转换为后缀表达式,并存放在temp,txt文件中;随后从temp.txt中读取后缀表达式,并将计算结果输入到output.txt中。

一个char类型的栈“Whereat”用来记录后缀表达式中操作数和运算符号的顺序,以决定需要多少次计算。

3.2程序代码#include <stdio.h>#include <stdlib.h>#include <math.h>int PrintError = 0;/*全局变量,0代表正常,1代表表达式出错*//*char类型链表式堆栈,用来存放运算符号,以及用在中缀表达式转换等时候*/typedef struct Node *PtrToNode;typedef PtrToNode Stack;int IsEmpty(Stack S);void MakeEmpty(Stack S);void Push(char X,Stack S);char Top(Stack S);void Pop(Stack S);typedef struct Node{char Element;PtrToNode Next;};/*float类型链表式堆栈,用来存放操作数*/typedef struct FNode *Ptr_Fn;typedef Ptr_Fn FStack;int FisEmpty(FStack S);void FPush(float X,FStack S);float FTop(FStack S);void FPop(FStack S);typedef struct FNode{float Element;Ptr_Fn Next;};void ConvertToPost(FILE *In, Stack Whereat,FILE *Temp);void Reverse(Stack Rev);void Calculate(FILE *Change, Stack Whereat,FILE *Temp);/******主函数******/int main(){FILE *InputFile, *OutputFile,*Temp;/*初始化变量*/Stack Whereat;char sample;InputFile = fopen("Input.txt","r");/*打开文件*/OutputFile = fopen("Output.txt","w");Whereat = malloc(sizeof(struct Node)); /*给 Whereat分配空间*/Whereat->Next = NULL;if (!InputFile || !OutputFile) { /*错误处理*/ printf("intput or output file(s) do not exist.\n");return(1);}sample = getc(InputFile);while ( sample != EOF){Temp = fopen("Temp.txt","w+"); /*生成Temp文件*/ungetc(sample,InputFile); /* put back sample字符*/ConvertToPost(InputFile,Whereat,Temp); /*中缀变后缀*/if (PrintError){ /*错误处理*/fprintf(OutputFile,"Error in infix notation.");printf("Error in infix notation.\n");fscanf(InputFile,"\n",&sample);PrintError = 0;}else if (IsEmpty(Whereat) == 1){ /*跳过在input文件中的空格*/}else if (IsEmpty(Whereat) != 1){Reverse(Whereat);if (Top(Whereat) == 'B'){ /*错误处理,*//*A表示操作数B表示运算符*/PrintError = 1; /*后缀表达式第一个元素应是操作数而不是运算符号*/}fclose(Temp);Temp = fopen("Temp.txt","r+");Calculate(OutputFile, Whereat,Temp);/*计算结果*/}fclose(Temp);MakeEmpty(Whereat); /* 清空Whereat用来处理下一行*/putc('\n',OutputFile);/* 在输出文件中换行*/sample = getc(InputFile);} /* While循环结束*/free(Whereat);fclose(InputFile);fclose(OutputFile);remove("Temp.txt"); /* 删除Temp.txt*/return 1;}/******检查堆栈是否为空******/int IsEmpty(Stack S){return(S->Next==NULL);}/******检查float堆栈是否为空******/int FIsEmpty(FStack S){return(S->Next==NULL);}/******弹出栈顶元素******/void Pop(Stack S){PtrToNode FirstCell;if (IsEmpty(S))perror("Empty Stack");else{FirstCell = S->Next;S->Next = S->Next->Next;free(FirstCell);}}/******弹出float栈顶元素******/void FPop(FStack S){Ptr_Fn FirstCell;if (FIsEmpty(S))perror("Empty Stack");else{FirstCell = S->Next;S->Next = S->Next->Next;free(FirstCell);}}/******将堆栈置空******/void MakeEmpty(Stack S){if (S == NULL)perror("Must use Createstack first");elsewhile (!IsEmpty(S))Pop(S);}/******将float堆栈置空******/void FMakeEmpty(FStack S){if (S == NULL)perror("Must use Createstack first");elsewhile (!IsEmpty(S))Pop(S);}/******元素进栈******/void Push(char X, Stack S){PtrToNode TmpCell;TmpCell = (PtrToNode)malloc(sizeof(struct Node));if (TmpCell == NULL)perror("Out of Space!");else{TmpCell->Element = X;TmpCell->Next = S->Next;S->Next = TmpCell;}}/******float元素进栈******/void FPush(float X, FStack S){Ptr_Fn TmpCell;TmpCell = (Ptr_Fn)malloc(sizeof(struct FNode));if (TmpCell == NULL)perror("Out of Space!");else{TmpCell->Element = X;TmpCell->Next = S->Next;S->Next = TmpCell;}}/******返回栈顶元素******/char Top(Stack S){if (!IsEmpty(S))return S->Next->Element;perror("Empty Stack");exit(1);return 0;}/******返回float栈顶元素******/float FTop(FStack S){if (!FIsEmpty(S))return S->Next->Element;perror("Empty Stack");exit(1);return 0;}/******将堆栈元素倒置******/void Reverse(Stack Rev){Stack Tempstack;Tempstack = malloc(sizeof(struct Node));Tempstack->Next = NULL;while (!IsEmpty(Rev)){Push(Top(Rev),Tempstack); /*将元素压栈到一个临时堆栈*/Pop(Rev);}Rev->Next = Tempstack->Next; /*指向新的堆栈*/ }/*******Whereat 说明:Whereat 记录了操作数和运算符号的位置,用A和B区分。

相关文档
最新文档