利用栈实现表达式求解
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; }。
数据结构-表达式求值
数据结构:线性结构—栈实现表达式求值一.问题分析利用栈这种数据结构存储数字和运算符,并实现表达式求值。
为实现按运算符优先顺序进行计算,需要在执行程序的过程中对运算符的优先顺序做出判断。
利用栈先进后出的特点,同时保证优先级最高的运算符始终在栈顶。
当栈顶元素优先级低于读入的运算符时,将该栈顶运算符推出。
这就保证了优先级高的运算符先计算。
二.数据结构—栈1.优先关系表:prior[7][7]={// +-*/()#'>','>','<','<','<','>','>','>','>','<','<','<','>','>','>','>','>','>','<','>','>','>','>','>','>','<','>','>','<','<','<','<','<','=',' ','>','>','<','>',' ','>','>','<','<','<','<','<',' ','='};将关系表直接用字符型的二维数组存储。
实验二--栈的应用---算术表达式的计算
浙江大学城市学院实验报告课程名称数据结构与算法实验项目名称实验二栈的应用---算术表达式的计算实验成绩指导老师(签名)日期一.实验目的和要求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语言1. 引言1.1 概述本文将讨论基于栈的后缀算术表达式求值的实现过程。
后缀算术表达式(也称为逆波兰表达式)是一种无需括号即可进行运算的表达式表示方法,它将操作符置于操作数之后。
相较于传统的中缀表达式,在计算机程序中处理后缀表达式更为高效和简洁。
1.2 文章结构文章分为五个主要部分:引言、栈的概念及原理、后缀算术表达式的定义和转换、基于栈的后缀算术表达式求值算法实现以及结论与总结。
在引言部分,我们将首先介绍本文的概述和目标,对后续内容进行简要说明。
1.3 目的通过本文,我们旨在让读者了解栈数据结构的基本概念和原理,并且掌握如何利用栈来实现对后缀算术表达式进行求值的算法。
同时,我们将介绍后缀算术表达式的定义和转换方法,并给出基于栈实现该计算方式的详细步骤与示例代码。
通过深入研究并学习这些内容,读者可以加深对栈数据结构和后缀算术表达式的理解,并且能够应用所学知识解决实际问题。
本文不仅适用于计算机科学或相关专业的学生,也适合对数据结构和算法感兴趣的读者阅读和学习。
2. 栈的概念及原理2.1 栈的定义栈是一种具有特定限制条件的线性数据结构,它具备“先进后出”(Last-In-First-Out,LIFO)的特性。
栈可以看作是一个容器,其中可以存储各种类型的数据。
与实际生活中的堆栈类似,栈只允许在其末尾进行插入和删除操作。
在栈中,最后加入的元素首先被访问和处理。
这是由于栈内元素之间的相对位置关系决定的。
插入操作称为“压栈”(Push),删除操作称为“弹栈”(Pop),而从栈顶读取元素或获取栈顶元素但不删除它称为“查看”(Peek)。
2.2 栈的基本操作推入元素:将一个元素添加到栈顶。
如果已经存在满员条件,则无法执行此操作。
弹出元素:从栈顶移除一个元素,并返回移除的值。
如果没有任何元素存在,则无法执行此操作。
查看栈顶元素:获取位于栈顶处的元素值,但不对其进行删除。
判断是否为空:检查栈是否为空。
表达式求值算法总结(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))```四、总结算术表达式求值是一项常见的数学运算任务,利用栈这一数据结构来实现求值算法是一种简单有效的方法,它将中缀表达式转化为逆波兰表达式后,可以消除括号并减少运算符的优先级关系,从而提高程序的执行效率。
栈的应用实验报告心得
栈的应用实验报告心得栈的应用实验报告心得一、引言栈(Stack)是一种常用的数据结构,具有先进后出(Last In First Out,简称LIFO)的特点。
在实际应用中,栈有着广泛的应用,例如函数调用、递归、表达式求值、括号匹配等。
为了更好地理解栈的应用,我们进行了一系列实验。
二、实验目的理解栈的基本概念和特点;掌握栈的基本操作,包括入栈、出栈、判空、读栈顶等;熟悉栈的应用场景,如逆波兰表达式求值、中缀表达式转后缀表达式等。
三、实验内容实现栈的基本操作:入栈、出栈、判空、读栈顶;实现逆波兰表达式求值算法;实现中缀表达式转后缀表达式算法;运用栈解决实际问题,如括号匹配等。
四、实验步骤及结果实验步骤(1)根据实验要求,设计栈的数据结构,并实现基本操作;(2)实现逆波兰表达式求值算法,通过入栈、出栈操作进行运算;(3)实现中缀表达式转后缀表达式算法,通过栈的特性进行转换;(4)运用栈解决括号匹配问题,通过入栈、出栈操作进行判断。
实验结果通过实验,我们成功实现了栈的基本操作,并运用栈解决了逆波兰表达式求值、中缀表达式转后缀表达式以及括号匹配等问题。
实验结果表明,栈在解决这些问题上具有很好的效果和应用价值。
五、实验心得通过本次实验,我对栈的概念和特点有了更深入的理解。
栈的先进后出特点使得其在很多实际问题中具有很好的应用场景。
在实现栈的过程中,我学会了如何设计栈的数据结构,并实现其基本操作。
通过实现逆波兰表达式求值算法和中缀表达式转后缀表达式算法,我进一步加深了对栈的理解,并熟悉了栈在算法中的应用。
同时,通过解决括号匹配问题,我认识到栈在实际问题中的实用性和重要性。
在实验过程中,我遇到了一些困难,如算法的设计和实现过程中的错误,以及对栈操作的理解等。
但通过努力和与同学的讨论,我逐渐克服了这些困难,并取得了较好的实验结果。
这次实验让我深刻认识到了理论与实践的关系,只有通过实际操作,才能更好地理解和应用理论知识。
基于栈结构的中缀表达式求值
实验三基于栈结构的中缀表达式求值班级:计科131、问题描述从键盘输入一中缀表达式字符串,读字符串,利用栈结构实现表达式求值。
2、输入与输出输入:从键盘中缀表达式如: 32+5×(6-4)输出:计算结果423、需求分析1.定义两个栈结构,数栈用于存放表达式中的数,符号栈用于存放表达式中的符号,实现栈的运算2.在读数的时候考虑多位运算3.实现表达式求值4、开发工具与环境硬件设备:微型计算机系统软件环境:操作系统Windows,开发工具等等5、概要设计1.结构定义typedef struct /* 运算符栈 */{ char *base,*top;int stacksize;}SqStack;typedef struct /* 运算数栈 */{ int *base,*top;int stacksize;}SqStack1;int priority[7][7]={{'>', '>', '<', '<', '<', '>', '>'}, // +{'>', '>', '<', '<', '<', '>', '>'}, // -{'>', '>', '>', '>', '<', '>', '>'}, // *{'>', '>', '>', '>', '<', '>', '>'}, // /{'<', '<', '<', '<', '<', '=', }, // ({'>', '>', '>', '>', ' ', '>', '>'}, // ){'<', '<', '<', '<', '<', ' ', '='} // #};/*用于比较符号优先级的全局二维数组*/2.各函数模块void InitStack(SqStack *s);操作结果:初始化运算符栈。
栈的应用——表达式求值
栈的应⽤——表达式求值 表达式求值是程序设计语⾔编译中的⼀个基本问题,它的实现就是对“栈”的典型应⽤。
本⽂针对表达式求值使⽤的是最简单直观的算法“算符优先法”。
本⽂给出两种⽅式来实现表达式求值,⽅式⼀直接利⽤中缀表达式求值,需要⽤到两个栈,操作数栈和操作符栈。
⾸先置操作数栈为空栈,操作符栈仅有“#”⼀个元素。
依次读⼊表达式中的每个字符,若是操作数则进操作数栈,若是操作符则和操作符栈的栈顶运算符⽐较优先权作相应操作,直⾄整个表达式求值完毕。
⽅式⼆⾸先把中缀表达式转换为后缀表达式并存储起来,然后利⽤读出的后缀表达式完成求值,其本质上是⽅式⼀的分解过程。
表达式求值的代码如下:#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;} 为了⽅便起见,本⽂只是简单的设计了⼀个针对⼀位整数的四则运算进⾏求值的算法,对于处理多位整数的四则运算,需要对本⽂接受输⼊的数据类型进⾏“升阶”,把字符数组换成字符串数组,将⼀个整数的多位数字存⼊⼀个字符串进⾏处理。
数据结构_用堆栈知识实现简单的多项式计算问题
/*jisuanqi_head.h*/
/*2012年4月15日
made by liuhui*/
#define MAX 1000
struct save1
{
float n[MAX];
int top;
}stack1;
structsave2
{
char n[MAX];
int top;
}stack2;
说明几个函数:
bool stackempty(save1 s)用来判断操作数栈s是否为空。
void push(save1 &s,char e)若栈满则输出“栈已满”,否则将元素e入栈
void pop(save1 &s, char &e)若栈为空则输出“栈为空”,否则将栈顶元素赋给e
bool stackempty2(save2 s)用来判断运算符栈s是否为空。
{
cout<<"栈已满"<<endl;
return ;
}
s.top++;
s.n[s.top]=e;
}
void push2(save2 &s,char e)//将e入栈
{
if(s.top==MAX-1)
{
cout<<"栈已满"<<endl;
void pop(save1 &s,float &e);//将栈顶元素出栈,存到e中
void pop2(save2 &s,char &e);//将栈顶元素出栈,存到e中
int in(char e);//e在栈内的优先级别
int out(char e);//e在栈外的优先级别
用栈解决表达式求值问题的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.栈的特点是后进先出(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.利用栈可以将中缀表达式转换为后缀表达式,并通过对后缀表达式的求值获得最终结果。
利用栈进行表达式求值
myStack.top = myStack.base + myStack.stacksize;
myStack.stacksize += STACKINCREMENT;
#include "Stdafx.h"
#include <stdio.h>
#include <malloc.h>
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef struct {
int *base;
int *top;
int stacksize;
if(isNum(c)) {
push(opnd, ((int)c-48));
c = getchar();
} else {
switch(precede((char)getTop(oprt), c)) {
case '<' : push(oprt, c); c = getchar(); break;
case '=' : pop(oprt, t); c = getchar(); break;
default : return '>';
} break;
case '(' :
switch (c2) {
case ')' : return '='; break;
栈的应用实验报告
栈的应用实验报告栈的应用实验报告引言:栈是一种常见的数据结构,它具有后进先出(Last In First Out,LIFO)的特点。
在计算机科学中,栈被广泛应用于各种领域,如编译器、操作系统、图形处理等。
本实验旨在通过实际应用场景,探索栈的应用。
一、栈的基本概念和操作栈是一种线性数据结构,它由一系列元素组成,每个元素都有一个前驱元素和一个后继元素。
栈的基本操作包括入栈(Push)和出栈(Pop)。
入栈将元素添加到栈的顶部,而出栈则将栈顶元素移除。
此外,栈还具有查看栈顶元素(Top)和判断栈是否为空(IsEmpty)的操作。
二、栈在表达式求值中的应用栈在表达式求值中发挥着重要作用。
例如,当我们需要计算一个数学表达式时,可以通过将表达式转换为后缀表达式,并利用栈来进行求值。
栈中存储操作数,当遇到运算符时,从栈中弹出相应数量的操作数进行计算,再将结果入栈。
通过这种方式,我们可以实现高效的表达式求值。
三、栈在函数调用中的应用栈在函数调用中也扮演着重要角色。
当我们调用一个函数时,计算机会将函数的返回地址、参数和局部变量等信息存储在栈中。
这样,当函数执行完毕后,可以从栈中恢复之前的上下文,继续执行调用函数的代码。
栈的这种特性使得递归函数的实现成为可能,同时也为程序的模块化提供了便利。
四、栈在迷宫求解中的应用栈在迷宫求解中也能发挥重要作用。
当我们需要找到从起点到终点的路径时,可以利用栈来存储当前路径上的位置。
从起点开始,我们按照某种策略选择下一个位置,并将其入栈。
如果当前位置无法继续前进,则将其出栈,并选择下一个位置。
通过不断重复这个过程,直到找到终点或者栈为空,我们就能得到迷宫的解。
五、栈在撤销和恢复操作中的应用栈在撤销和恢复操作中也能发挥重要作用。
当我们在编辑文档或者绘图时,经常需要进行撤销和恢复操作。
栈可以用来记录每次操作的状态,当用户选择撤销时,从栈中弹出最近的操作,并将文档或图形恢复到之前的状态。
通过这种方式,我们可以提供良好的用户体验,同时也方便用户进行操作的回溯。
VB利用栈实现表达式求值
实验一Dim s(100) As String, t As IntegerPrivate Sub Command2_Click()Dim x As String, n, i As IntegerText3.Text = " "For i = t To 1 Step -1pop x, s(), tText3.Text = Text3.Text & xNext iEnd SubPrivate Sub Command1_Click()Dim a, b, x As String, n, i, m As IntegerText2.Text = ""a = Text1.Textn = Len(a)m = 10t = 0For i = 1 To nx = Mid(a, i, 1)PUSH x, s(), m, tText2.Text = Text2.Text & s(i)Next iEnd SubPublic Sub PUSH(x As String, s() As String, m As Integer, top As Integer)If (top = m) ThenMsgBox "数据有误"EndEnd Iftop = top + 1s(top) = x End SubPublic Sub pop(x, s() As String, top As Integer) If top = 0 ThenMsgBox "栈空"End Ifx = s(top)top = top - 1End SubPublic Sub pre(x As String, p As Integer)Select Case xCase "*"p = 2Case "+"p = 1Case "-"p = 1Case ";"p = 0Case "^"p = 3End SelectEnd SubPrivate Sub Command3_Click()Dim topo As Integer, topn As IntegerDim p, f, i, x1, y1 As IntegerDim a1 As Integer, a2 As IntegerDim y, os(100) As StringDim a As String, x As StringDim z As String, w As StringDim ns(100) As String, q As Stringtopo = 0topn = 0z = ";"f = 0PUSH z, os(), 10, topoi = 0a = Text1.TextDo While f <> 2If f = 0 Theni = i + 1w = Mid(a, i, 1)End IfIf Not ((w = "*") Or (w = "+") Or (w = "-") Or (w = "/") Or (w = "^") Or (w = ";")) ThenPUSH w, ns(), 10, topnElsetp q, os(), topopre w, a1pre q, a2If (a1 > a2) ThenPUSH w, os(), 10, topof = 0ElseIf (q = ";") And (w = ";") Thenpop x, ns(), topnf = 2Elsepop x, ns(), topnpop y, ns(), topnpop q, os(), topox1 = Val(x)y1 = Val(y) Select Case qCase "*"x1 = y1 * x1Case "/"x1 = y1 / x1Case "+"x1 = y1 + x1Case "-"x1 = y1 - x1Case "'"x1 = y1 ^ x1End Selectx = Str(x1)PUSH x, ns(), 10, topnf = 1End IfEnd IfLoopText4.Text = Str(x1)End SubPrivate Sub Form_Load()Text1.Text = ""Text2.Text = ""End SubPublic Sub tp(x, s() As String, top As Integer) If top = 0 ThenMsgBox "栈空"End Ifx = s(top)End Sub。
举出4个用栈解决问题的例子
举出4个用栈解决问题的例子栈是一种重要的数据结构,主要用于模拟现实世界中的各种运算,而且它也可以用来解决复杂的问题。
栈的特点是在存储数据的同时,具有“后进先出”的原则,因此在解决一些问题时,有时会使用栈来设计算法,以解决复杂的问题。
本文将举出4个使用栈解决问题的例子,以供大家参考。
1. 中缀表达式转后缀表达式。
中缀表达式是常见的表达式,表达式中各运算符与操作数的位置是混合着的,而后缀表达式则是运算符与操作数一一对应,表达式中的运算符均在后面,因此要把中缀表达式转换成后缀表达式,就需要使用栈来储存操作数和运算符,从而实现将中缀表达式转换为后缀表达式。
2.诺塔。
汉诺塔是一个古老的游戏,它涉及在三根柱子之间移动碟子,每个时刻只能移动一个碟子,且大的碟子不能在小的碟子之上,而在计算机中模拟这个游戏时,可以使用栈来模拟,把每根柱子看作一个栈,碟子就看作放在栈中的元素,每次移动时,就是从某根柱子的栈顶取出碟子,放入另一根柱子的栈顶,从而实现移动的目的。
3.译器的词法分析。
编译器在处理输入的源代码时,首先要进行语法分析,将源代码切分成一个一个有意义的语言单位,这个过程就称为词法分析。
在词法分析中需要处理的两个困难是状态跳转和字符串的回溯,而使用栈来处理这两个困难就显得非常有效,比如字符串的回溯问题,就可以使用栈来储存源代码中扫描到的字符,以便反向查找,而在状态跳转中,也可以使用栈记录当前的状态是什么,以便在需要的时候进行回溯。
4.号匹配。
括号匹配是一类常见的问题,比如HTML文件中的括号要正确匹配,否则整个文件就会变得混乱,而为了检查括号是否匹配,使用栈就是一个很有效的解决方法,遍历文件,每当遇到一个“(”时,就将它压入栈中,而每当遇到一个“)”时,则从栈中弹出一个“(”,如果遇到“)”时栈中已经没有“(”,则说明括号不匹配,否则遍历完毕后,如果栈中还有“(”,则说明“(”多于“)”,否则括号就正确匹配了。
以上就是使用栈解决问题的4个例子,从这4个例子可以看到,栈的特性使其在解决某些复杂的问题时显得非常有用。
c语言中缀、后缀算术表达式求值用栈实现
c语言中缀、后缀算术表达式求值用栈实现下面是用栈实现中缀表达式求值的示例代码:#include <stdio.h>#include <stdlib.h>#include <ctype.h>#define MAX_STACK_SIZE 100typedef struct {int top;int data[MAX_STACK_SIZE];} Stack;void init(Stack *s) {s->top = -1;}int is_empty(Stack *s) {return s->top == -1;}int is_full(Stack *s) {return s->top == MAX_STACK_SIZE - 1;}void push(Stack *s, int x) {if (is_full(s)) {printf("Error: stack overflow\n");exit(EXIT_FAILURE);}s->data[++s->top] = x;}int pop(Stack *s) {if (is_empty(s)) {printf("Error: stack underflow\n");exit(EXIT_FAILURE);}return s->data[s->top--];}int peek(Stack *s) {if (is_empty(s)) {printf("Error: stack underflow\n");exit(EXIT_FAILURE);}return s->data[s->top];}int precedence(char op) {switch (op) {case '+':case '-':return 1;case '*':case '/':return 2;default:return 0;}}int evaluate(int op1, int op2, char op) {switch (op) {case '+':return op1 + op2;case '-':return op1 - op2;case '*':return op1 * op2;case '/':return op1 / op2;default:printf("Error: invalid operator\n");exit(EXIT_FAILURE);}}int evaluate_infix(char *expr) {Stack op_stack, val_stack;init(&op_stack);init(&val_stack);while (*expr != '\0') {if (isdigit(*expr)) {int val = 0;while (isdigit(*expr)) {val = val * 10 + (*expr - '0');expr++;}push(&val_stack, val);} else if (*expr == '+' || *expr == '-' || *expr == '*' || *expr == '/') {while (!is_empty(&op_stack) && precedence(peek(&op_stack)) >= precedence(*expr)) {int op2 = pop(&val_stack);int op1 = pop(&val_stack);char op = pop(&op_stack);push(&val_stack, evaluate(op1, op2, op));}push(&op_stack, *expr);expr++;} else if (*expr == '(') {push(&op_stack, '(');expr++;} else if (*expr == ')') {while (peek(&op_stack) != '(') {int op2 = pop(&val_stack);int op1 = pop(&val_stack);char op = pop(&op_stack);push(&val_stack, evaluate(op1, op2, op));}pop(&op_stack);expr++;} else {printf("Error: invalid character\n");exit(EXIT_FAILURE);}}while (!is_empty(&op_stack)) {int op2 = pop(&val_stack);int op1 = pop(&val_stack);char op = pop(&op_stack);push(&val_stack, evaluate(op1, op2, op));}return peek(&val_stack);}int main() {char expr[100];printf("Enter infix expression: ");scanf("%[^\n]", expr);printf("Result = %d\n", evaluate_infix(expr));return 0;}下面是用栈实现后缀表达式求值的示例代码:#include <stdio.h>#include <stdlib.h>#include <ctype.h>#define MAX_STACK_SIZE 100typedef struct {int top;int data[MAX_STACK_SIZE];} Stack;void init(Stack *s) {s->top = -1;}int is_empty(Stack *s) {return s->top == -1;}int is_full(Stack *s) {return s->top == MAX_STACK_SIZE - 1;}void push(Stack *s, int x) {if (is_full(s)) {printf("Error: stack overflow\n");exit(EXIT_FAILURE);}s->data[++s->top] = x;}int pop(Stack *s) {if (is_empty(s)) {printf("Error: stack underflow\n");exit(EXIT_FAILURE);}return s->data[s->top--];}int peek(Stack *s) {if (is_empty(s)) {printf("Error: stack underflow\n");exit(EXIT_FAILURE);}return s->data[s->top];}int evaluate(int op1, int op2, char op) {switch (op) {case '+':return op1 + op2;case '-':return op1 - op2;case '*':return op1 * op2;case '/':return op1 / op2;default:printf("Error: invalid operator\n");exit(EXIT_FAILURE);}}int evaluate_postfix(char *expr) {Stack stack;init(&stack);while (*expr != '\0') {if (isdigit(*expr)) {int val = 0;while (isdigit(*expr)) {val = val * 10 + (*expr - '0');expr++;}push(&stack, val);} else if (*expr == '+' || *expr == '-' || *expr == '*' || *expr == '/') { int op2 = pop(&stack);int op1 = pop(&stack);push(&stack, evaluate(op1, op2, *expr));expr++;} else {printf("Error: invalid character\n");exit(EXIT_FAILURE);}}return peek(&stack);}int main() {char expr[100];printf("Enter postfix expression: ");scanf("%[^\n]", expr);printf("Result = %d\n", evaluate_postfix(expr));return 0;}。
数据结构C语言版_栈实现表达式求值
break;
case'=':
Pop(&OPTR,&x); // 脱括号并接收下一字符
c=getchar();
break;
case'>':
Pop(&OPTR,&theta); // 退栈并将运算结果入栈
switch(theta)
{
case'+':
c=a+b+48;
break;
case'-':
c=a-b+48;
break;
case'*':
c=a*b+48;
break;
case'/':c=a/b+48;
}
return c;
}
// 算法3.4 P54
}SqStack; // 顺序栈
// 构造一个空栈S。
int InitStack(SqSt的存储空间
(*S).base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
default:
f='>';
}
}
return f;
}
// 判断c是否为运算符
int In(SElemType c)
{
switch(c)
{
case'+':
case'-':
case'*':
c语言顺序栈实现表达式求值
c语言顺序栈实现表达式求值下面是C语言顺序栈实现表达式求值的代码示例:```c#include <stdio.h>#include <stdlib.h>#define MAX_EXPR_LEN 100typedef struct {double* data; // 存储数据的数组指针int top; // 栈顶指针int maxSize; // 栈的最大容量} Stack;// 初始化栈void init(Stack* stack, int maxSize) {stack->data = (double*)malloc(maxSize * sizeof(double));stack->top = -1;stack->maxSize = maxSize;}// 判断栈是否为空int isEmpty(Stack* stack) {return stack->top == -1;}// 判断栈是否已满int isFull(Stack* stack) {return stack->top == stack->maxSize - 1;}// 入栈void push(Stack* stack, double value) {if (isFull(stack)) {printf("Stack is full.\n");return;}stack->data[++stack->top] = value;}// 出栈double pop(Stack* stack) {if (isEmpty(stack)) {printf("Stack is empty.\n");return -1;}return stack->data[stack->top--];}// 获取栈顶元素double top(Stack* stack) {if (isEmpty(stack)) {printf("Stack is empty.\n");return -1;}return stack->data[stack->top];}// 运算符优先级比较int priority(char op) {switch(op) {case '+':case '-':return 1;case '*':case '/':return 2;case '(':case ')':return 0;default:return -1;}}// 执行操作double operate(double operand1, double operand2, char op) { switch(op) {case '+':return operand1 + operand2;case '-':return operand1 - operand2;case '*':return operand1 * operand2;case '/':return operand1 / operand2;default:return 0;}}// 表达式求值double evaluateExpression(char* expression) {Stack operandStack; // 操作数栈Stack operatorStack; // 运算符栈init(&operandStack, MAX_EXPR_LEN);init(&operatorStack, MAX_EXPR_LEN);int i = 0;while (expression[i] != '\0') {if (expression[i] >= '0' && expression[i] <= '9') {// 处理数字double num = 0;while (expression[i] >= '0' && expression[i] <= '9') {num = num * 10 + (expression[i] - '0');i++;}push(&operandStack, num);} else if (expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/') {// 处理运算符while (!isEmpty(&operatorStack) && priority(expression[i]) <= priority(top(&operatorStack))) {char op = pop(&operatorStack);double operand2 = pop(&operandStack);double operand1 = pop(&operandStack);double result = operate(operand1, operand2, op);push(&operandStack, result);}push(&operatorStack, expression[i]);i++;} else if (expression[i] == '(') {// 处理左括号push(&operatorStack, expression[i]);i++;} else if (expression[i] == ')') {// 处理右括号while (top(&operatorStack) != '(') {char op = pop(&operatorStack);double operand2 = pop(&operandStack);double operand1 = pop(&operandStack);double result = operate(operand1, operand2, op);push(&operandStack, result);}// 弹出左括号pop(&operatorStack);i++;} else {i++;}}// 处理剩余的运算符while (!isEmpty(&operatorStack)) {char op = pop(&operatorStack);double operand2 = pop(&operandStack);double operand1 = pop(&operandStack);double result = operate(operand1, operand2, op);push(&operandStack, result);}double result = pop(&operandStack);return result;}int main() {char expression[MAX_EXPR_LEN];printf("请输入表达式:");fgets(expression, sizeof(expression), stdin);double result = evaluateExpression(expression);printf("表达式的结果为:%lf\n", result);return 0;}```使用该代码,可以实现对不带括号的四则运算表达式进行求值。
栈实现表达式的简单求值
利用栈编写表达式求值程序:输入含有“+”、“-”、“*”、“/”四则运算的表达式,其中负数要用(0-正数)表示,并以=结束。
要求输出表达式的值此题目可选做。
注意:计算的结果数值不可以大于79.#include<stdio.h>#include<malloc.h>#define OK 1#define ERROR 0#define STACK_INIT_SIZE 100 // 存储空间初始分配量typedef struct{char *base;char *top;int stacksize;}Stack;int InitStack(Stack &S){S.base=(char *)malloc(STACK_INIT_SIZE*sizeof(char)); if(!S.base) return ERROR;S.top=S.base;S.stacksize=STACK_INIT_SIZE;return OK;}int Pop(Stack &S,char &e){if(S.top==S.base) return ERROR;e=*--S.top;return OK;}int GetTop(Stack S,char &e){if(S.top==S.base) return ERROR;e=*--S.top;return OK;}int Push(Stack &S,char ch){if(S.top-S.base>=S.stacksize){S.base=(char*)realloc(S.base,(S.stacksize+10)*sizeof(char)); if(!S.base) return ERROR;S.top=S.base+S.stacksize;S.stacksize+=10;}*S.top++=ch;return OK;}char Compare(char &e,char ch){switch(e){case '+':if(ch=='+'||ch=='-'||ch==')') return '>';else return '<';break;case '-':if(ch=='+'||ch=='-'||ch==')') return '>';else return '<';break;case '*':if(ch=='(')return '<';else return '>';break;case '/':if(ch=='(')return '<';else return '>';break;case '(':if(ch==')')return '=';else return '<';break;case ')':return '>';break;}}int Cal(char a,char theta,char b) {int s;a-=48;b-=48;switch(theta){case '+':s=a+b;break;case '-':s=a-b;break;case '*':s=a*b;break;case '/':s=a/b;break;}return s;}int StackEmpty(Stack S){if(S.top==S.base) return OK; return ERROR;}int Operator(){Stack CS;Stack NS;char ch,e;char a,b,theta;InitStack(CS);InitStack(NS);//Push(CS,'=');ch=getchar();while(ch!='='){if(ch>='0'&&ch<='9'){Push(NS,ch);ch=getchar();if(ch>='0'&&ch<='9'){Pop(NS,a);Push(NS,((a-48)*10+(ch-48))+48); ch=getchar();}}else{if(StackEmpty(CS)){Push(CS,ch);ch=getchar(); continue;}GetTop(CS,e);switch(Compare(e,ch)) {case '<':Push(CS,ch); ch=getchar();break;case '=':Pop(CS,e);ch=getchar();break;case '>':Pop(CS,theta);Pop(NS,a);Pop(NS,b);Push(NS,Cal(b,theta,a)+48); break;}}}while(Pop(CS,theta)){Pop(NS,a);Pop(NS,b);Push(NS,(Cal(b,theta,a)+48)); }GetTop(NS,ch);return (ch-48);}int main(){printf("%d\n",Operator()); return 0;}输入格式第一行:一个算术表达式输出格式第一行:算术表达式的值输入样例3*(9-7)=(0-12)*((5-3)*3)/(2+2)=输出样例6-18。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.2 C语言
C语言既有高级语言的特点,又具有汇编语言的特点;既是一个成功的系统设计语言,有时一个使用的程序设计语言;既能用来编写不依赖计算机硬件的应用程序,又能用来编写各种系统程序;是一种受欢迎、应用广泛的程序设计语言。
1.4任务与分析
本程序用于解决一个可以带括号的表达式求值的问题,要运用到栈,而且会用到一种简单直观,广为使用的算法,通常称为“算符优先法”。进行表达式求值首先要了解算术四则运算的规则。即:(1)先乘除,后加减;(2)从左算到右;(3)先括号内后括号外;算符优先法根据这个算符优先关系的规定来实现对表达式的编译或解释执行的。任何一个表达式都是由操作数、运算符和界限符组成。
/*'('*/'<','<','<','<','<','=',' ',
/*')'*/'>','>','>','>',' ','>','>',
/*'#'*/'<','<','<','<','<',' ','=',
};
//==========对两操作数进行运算
floatOperate(floata,unsignedchartheta,floatb)
{
// 算术表达式求值的算符优先算法。
// 设OPTR和OPND分别为运算符栈和运算数栈,OPSET为运算符集合。
栈是一种重要的线性结构,栈可以用作数制转换、括号匹配的检验、行编辑程序等等问题中。从数据结构角度看,栈也是线性表,其特殊性在于栈的基本操作是线性表操作的子集,它是操作受限的线性表,因此,可称为限定性的数据结构。但从数据类型角度看,它是和线性表大不相同的两类重要的抽象数据类型。
栈实限定仅在表尾进行插入或删除操作的线性表。因此,对栈来说,表尾端有其特殊含义,称为栈顶,相应地,表头端称为栈底。不含元素的空表称为空栈。栈又称为后进先出的线性表。
printf("\n");
printf ("运算结果是:%d\n", nResult );
printf("\n");
break;
case0:
exit(0);
break;
}
}
return0;
}
3.4
//==========预定义
#defineok 1
#defineerror 0
#defineoverflow -1
这次的课程设计是利用栈实现表达式求解,要求只考虑+、-、*、/四种数学运算还有只考虑圆括号参与运算。
关键词:数据结构与算法, 栈, 表达式求解,最优
1.1问题的提出
栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。
cout<<"请输入选项:";
cin>>n;
switch(n)
{
case1:
puts ("**************************************************");
puts ("请输入一个运算式,以#结尾:");
printf("\n");
nResult = EvaluateExpression();
理学院
课程设计说明书
课 程 名 称:数据结构与算法A设计实践
课 程 代 码:6015059
题 目 二:利用栈实现表达式求解
开 始 时 间:2015年12月28日
完 成 时 间:2016年01月10日
课程设计成绩:
学习态度及平时成绩(30)
技术水平与实际能力(20)
创新(5)
说明书撰写质量(45)
总 分(100)
EvaluateExpression():用运算符优先级对算术表达式求值
最后,通过主函数对以上几个函数的调用,实现该系统的功能。
2.2 数据需求
输入一个表达式,利用优先级表对表达式求值。
3
3.1
为了实现算符优先算法使用两个工作栈,一个称作OPTR,以寄存运算符;另一个称作OPND,用以寄存操作数或运算结果。在操作数和操作符入栈前,通过一个函数来判别,输入的是操作数还是操作符,操作数入OPND,操作符入OPTR。在输入表达式的最后输入‘#’,设定‘#’的优先级最低,代表表达式输入结束。在表达式输入过程中,遇操作数则直接入栈,遇到运算符则与栈顶运算符比较优先级,若当前运算符优先级高,则当前运算符入栈,扫描下一符号;否则栈顶运算符出栈,两操作数出栈,进行运算,所得结果入数栈,重新比较当前运算符与新栈顶运算符。如此重复直到栈顶运算符与当前符号均为‘#’,运算结束。
(2)只考虑圆括号()参与运算
测试数据及测试结果请在上交的资料中写明;必须上机调试通过
按《数据结构课程设计大纲》中的要求完成课程设计报告格式。
设计结束后,每个学生必须上交的材料有:
1《课程设计报告》打印稿一份2.课程设计的源代码电子文档一份
四、主要技术路线提示
根据运算符号的优先级来决定当前符号是否入栈;注意考虑多重括号匹配的问题。
2 系统分析
2.1功能要求
2.1.1 总体要求
利用教材3.2.5节的理论实现表达式求解。
(1)只考虑+、-、*、/四种数学运算
(2)只考虑圆括号()参与运算
2.1.2本人所做模块
根据这次课程设计题目的要求,将这次任务分为了几个小的模块,具体模块的功能如下:
Push(&S,e):入栈函数模块
Pop(&S,&e):出栈函数模块
}
*S.top++=e;
returnok;
}
//===========出栈函数模板
template<typenameT1,typenameT2>
Status Pop(T1 &S,T2 &e)
{
if(S.top==S.base)
returnerror;
e=*--S.top;
returnok;
}
//===========获取栈顶元素模板
exit (overflow);
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
returnok;
}
//==========入栈函数模板
template<typenameT1,typenameT2>
Status Push(T1 &S,T2 e)
{
if(S.top-S.base>=S.stacksize)
2.严蔚敏等著,《数据结构》,清华大学出版社,2003
3.李芸芳等著,《软件技术基础》(第二版),清华大学出版社,2000
4.徐孝凯等著,《数据结构(C语言描述)》,清华大学出版社,2004
指导教师签名日期年月日
系 主 任审核日期年月日
摘
随着计算机的普遍应用与日益发展,其应用早已不局限于简单的数值运算,数据结构与算法的学习就是为以后利用计算机资源高效地开发非数值处理的计算机程序打下坚实的理论、方法和技术基础。数据结构与算法旨在分析研究计算机加工的数据对象的特性,以便选择适当的数据结构和存储结构,从而使建立在其上的解决问题的算法达到最优。
In(Test,* TestOp):判断是否为运算符
Operate(a,theta,b):根据theta对a、b进行四则运算操作
ReturnOpOrd(op,* TestOp):若TestOp为运算符,则返回此运算符在数组的下标
precede( Aop, Bop):根据运算符优先级表返回Aop与Bop之间的优先级
{
boolFind=false;
for(inti=0; i< OPSETSIZE; i++)
{
if(Test == TestOp[i])
Find=true;
}
returnFind;
}
//===========比较运算符间的优先关系
unsignedcharPrior[7][7] =
{
// 运算符优先级表
#defineOPSETSIZE 7
#defineSTACKINCREMENT 100
#defineSTACK_INIT_SIZE 10
//==========定义顺序栈结构模板
template<typenameT>
structSqStack
{
T *top;
T *base;
intstacksize;
{
switch(theta)
{
case'+':returna+b;
case'-':returna-b;
case'*':returna*b;