用两种方法实现表达式求值

合集下载

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

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

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

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

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

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

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

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

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

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

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

可以使用栈来实现。

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

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

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

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

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

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

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

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

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

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

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

数据队列实验报告总结(3篇)

数据队列实验报告总结(3篇)

第1篇一、实验背景数据结构是计算机科学中一个重要的基础学科,其中队列作为一种常用的数据结构,在计算机科学和实际应用中具有广泛的应用。

队列是一种先进先出(FIFO)的线性表,它允许在表的一端进行插入操作,在另一端进行删除操作。

本实验旨在通过实现队列的基本操作,加深对队列数据结构概念和特性的理解,并掌握其在实际应用中的运用。

二、实验目的1. 理解队列数据结构的概念和特性。

2. 掌握队列的存储结构,包括顺序存储和链式存储。

3. 熟悉队列的基本操作,如入队、出队、队列长度、队列状态判断等。

4. 通过实际编程,提高数据结构应用能力。

三、实验内容1. 队列的顺序存储结构实现:- 定义队列结构体,包含队列长度、队列最大长度、队列首尾指针等。

- 实现队列的初始化、入队、出队、判断队列是否为空、判断队列是否已满等操作。

2. 队列的链式存储结构实现:- 定义队列节点结构体,包含队列数据、指针等。

- 实现队列的初始化、入队、出队、判断队列是否为空、判断队列是否已满等操作。

3. 队列的实际应用:- 使用队列实现广度优先搜索(BFS)算法。

- 使用队列实现单链表反转。

- 使用队列实现表达式求值。

四、实验步骤1. 创建队列结构体,定义队列的基本属性和操作函数。

2. 实现队列的顺序存储结构,包括队列的初始化、入队、出队、判断队列是否为空、判断队列是否已满等操作。

3. 实现队列的链式存储结构,包括队列的初始化、入队、出队、判断队列是否为空、判断队列是否已满等操作。

4. 通过实际编程,验证队列的基本操作是否正确。

5. 使用队列实现实际应用,验证队列在解决问题中的应用价值。

五、实验结果与分析1. 顺序存储结构实现:- 队列的初始化、入队、出队、判断队列是否为空、判断队列是否已满等操作均能正常进行。

- 队列的顺序存储结构在插入和删除操作时,需要移动队列中的元素,因此时间复杂度为O(n)。

2. 链式存储结构实现:- 队列的初始化、入队、出队、判断队列是否为空、判断队列是否已满等操作均能正常进行。

栈和队列先进先出和后进先出的数据结构

栈和队列先进先出和后进先出的数据结构

栈和队列先进先出和后进先出的数据结构栈和队列是常用的数据结构,它们分别以先进先出(FIFO)和后进先出(LIFO)的方式来组织和管理数据。

在许多编程语言中,栈和队列被广泛应用于解决各种问题。

本文将从定义、特点、应用和实现这几个方面来介绍栈和队列。

一、定义栈(Stack)是一种只允许在固定一端进行插入和删除操作的线性数据结构。

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

栈的特点是先进后出。

队列(Queue)是一种先进先出的线性数据结构,允许在一端进行插入操作,而在另一端进行删除操作。

插入操作在队列的尾部进行,删除操作则在队列的头部进行。

二、特点2.1 栈的特点(1)插入和删除操作只能在栈顶进行,保证数据的顺序。

(2)栈是一种后进先出(LIFO)的数据结构,也就是最后插入的元素最先被删除。

(3)栈只能在栈顶进行插入和删除操作,不允许在中间或者底部进行操作。

2.2 队列的特点(1)插入操作只能在队列的尾部进行,保证数据的顺序。

(2)删除操作只能在队列的头部进行,始终删除最先插入的元素。

(3)队列是一种先进先出(FIFO)的数据结构,也就是最先插入的元素最早被删除。

三、应用3.1 栈的应用(1)函数调用和递归:栈被用于保存函数调用时的局部变量和返回地址。

(2)表达式求值:使用栈来实现中缀表达式转换为后缀表达式,然后计算结果。

(3)括号匹配:通过栈检查括号是否配对合法。

(4)浏览器的前进和后退:把浏览器的访问记录保存在栈中,方便前进和后退操作。

3.2 队列的应用(1)任务调度:使用队列管理任务,在现有任务执行完毕后按照先后顺序执行新任务。

(2)缓存管理:常用的缓存淘汰策略是先进先出,即最早进入缓存的数据最早被淘汰。

(3)消息队列:实现进程间的异步通信,提高系统的并发性和可扩展性。

(4)打印队列:打印任务按照先后顺序排队执行,保证打印的顺序。

四、实现栈和队列可以通过数组或链表来实现。

使用数组实现的栈和队列称为顺序栈和顺序队列,而使用链表实现的栈和队列称为链式栈和链式队列。

信息学奥赛知识点(十二)—栈和队列

信息学奥赛知识点(十二)—栈和队列

栈和队列是信息学竞赛中经常涉及的数据结构,它们在算法和程序设计中有着广泛的应用。

掌握栈和队列的基本原理和操作方法,对于参加信息学竞赛的同学来说是非常重要的。

本文将深入探讨栈和队列的相关知识点,帮助大家更好地理解和掌握这两种数据结构。

一、栈的定义与特点栈是一种先进后出(LIFO)的数据结构,它的特点是只允许在栈顶进行插入和删除操作。

栈可以用数组或链表来实现,常见的操作包括压栈(push)、出栈(pop)、获取栈顶元素(top)等。

栈的应用非常广泛,比如在计算机程序中,函数的调用和返回值的存储就是通过栈来实现的。

二、栈的基本操作1. 压栈(push):将元素压入栈顶2. 出栈(pop):将栈顶元素弹出3. 获取栈顶元素(top):返回栈顶元素的值,但不把它从栈中移除4. 判空:判断栈是否为空5. 获取栈的大小:返回栈中元素的个数三、栈的应用1. 括号匹配:利用栈来检查表达式中的括号是否匹配2. 表达式求值:利用栈来实现中缀表达式转换为后缀表达式,并进行求值3. 迷宫求解:利用栈来实现迷宫的路径搜索4. 回溯算法:在深度优先搜索和递归算法中,通常会用到栈来保存状态信息四、队列的定义与特点队列是一种先进先出(FIFO)的数据结构,它的特点是只允许在队尾进行插入操作,在队首进行删除操作。

队列同样可以用数组或链表来实现,常见的操作包括入队(enqueue)、出队(dequeue)、获取队首元素(front)、获取队尾元素(rear)等。

队列在计算机领域也有着广泛的应用,比如线程池、消息队列等都可以用队列来实现。

五、队列的基本操作1. 入队(enqueue):将元素插入到队列的末尾2. 出队(dequeue):从队列的头部删除一个元素3. 获取队首元素(front):返回队列的头部元素的值4. 获取队尾元素(rear):返回队列的尾部元素的值5. 判空:判断队列是否为空6. 获取队列的大小:返回队列中元素的个数六、队列的应用1. 广度优先搜索算法(BFS):在图的搜索中,通常会用队列来实现BFS算法2. 线程池:利用队列来实现任务的调度3. 消息队列:在分布式系统中,常常会用队列来进行消息的传递4. 最近最少使用(LRU)缓存算法:利用队列实现LRU缓存淘汰在信息学竞赛中,栈和队列的相关题目经常出现,并且有一定的难度。

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

C++四则运算表达式求值算法

C++四则运算表达式求值算法
的字符串。
u 这里定义了两个构造函数,不带参数的默认 m_string 为空,带 string 类型
参数的将参数值赋予成员变量 m_string,此外还定义了赋值运算符“=”,
目 的是将一个表达式字符串 赋予 成员变量 m_string 。 因此 生 成一个 ExpressionType 的对象可以有如下两种形式: ExpressionType expr(“(2.99-4.32)*(90.8-78.66)+78.0/3.14”); 或者 ExpressionType expr; Expr = “(2.99-4.32)*(90.8-78.66)+78.0/3.14”; u DivideExpressionToItem(): 私有成员函数,返回值是一个 string 类型的 队列。其功能是将原始的中缀表达式中的操作数、操作符以及括号按顺序以 字符串的形式分解出来,然后保存在一个队列中(队列的操作规则是先进先 出)。 u ChangeToSuffix(): 私有成员函数,返回值是一个 string 类型的栈。其功 能是将队列中表示原始表达式各项的字符串调整顺序,转换成后缀表达式的 顺序,并处理掉括号,然后保存在一个栈中(栈的操作规则是先进后出)。 u IsWellForm():私有成员函数,返回 bool 值。其功能是判断原始表达式中的 括号是否匹配,如果匹配返回 true,否则返回 false。 u Size():返回原始表达式所包含的字节数。 u Calculate(): 公有成员函数,返回 double 类型的值。其功能是计算转换后 的后缀表达式的值,即原始中缀表达式的值。
abc然后分别按从左到右放入栈中如果碰到操作符就从栈中弹出两个操作数进行运算最后再将运算结果放入栈中依次进行直到表达式放入栈中然后碰到操作符则从栈中弹出的运算并将其结果d假设为放入栈中最后是操作符所以再弹出进行dc运算并将其结果再次放入栈中此时表达式结束则栈中的元素值就是该表达式最后的运算结果

数据结构课程设计-表达式求值【完整版】

数据结构课程设计-表达式求值【完整版】

XXXXXX大学《数据结构》课程设计报告班级:学号:姓名:指导老师:目录一算术表达式求值一、需求分析二、程序得主要功能三、程序运行平台四、数据结构五、算法及时间复杂度六、测试用例七、程序源代码二感想体会与总结算术表达式求值一、需求分析一个算术表达式就是由操作数(operand)、运算符(operator)与界限符(delimiter)组成得。

假设操作数就是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号与表达式起始、结束符“#”,如:#(7+15)*(23—28/4)#。

引入表达式起始、结束符就是为了方便.编程利用“算符优先法”求算术表达式得值.二、程序得主要功能(1)从键盘读入一个合法得算术表达式,输出正确得结果。

(2)显示输入序列与栈得变化过程。

三、程序运行平台Visual C++6、0版本四、数据结构本程序得数据结构为栈。

(1)运算符栈部分:struct SqStack //定义栈{char *base; //栈底指针char *top; //栈顶指针intstacksize; //栈得长度};intInitStack (SqStack &s) //建立一个空栈S{if (!(s、base= (char *)malloc(50*sizeof(char))))exit(0);s、top=s、base;s、stacksize=50;return OK;}char GetTop(SqStack s,char &e) //运算符取栈顶元素{if (s、top==s、base) //栈为空得时候返回ERROR{ﻩ printf("运算符栈为空!\n");ﻩ return ERROR;}elsee=*(s、top-1); //栈不为空得时候用e做返回值,返回S得栈顶元素,并返回OK returnOK;}int Push(SqStack&s,char e) //运算符入栈{if (s、top—s、base >= s、stacksize)ﻩ{printf("运算符栈满!\n");ﻩs、base=(char*)realloc(s、base,(s、stacksize+5)*sizeof(char));//栈满得时候,追加5个存储空间if(!s、base)exit (OVERFLOW);s、top=s、base+s、stacksize;s、stacksize+=5;}ﻩ*(s、top)++=e;//把e入栈ﻩreturn OK;}int Pop(SqStack &s,char &e) //运算符出栈{if (s、top==s、base) //栈为空栈得时候,返回ERROR{printf("运算符栈为空!\n”);ﻩ return ERROR;}else{ﻩﻩe=*-—s、top;//栈不为空得时候用e做返回值,删除S得栈顶元素,并返回OK return OK;}}int StackTraverse(SqStack&s)//运算符栈得遍历{ﻩchar *t;ﻩt=s、base;ﻩif (s、top==s、base){ﻩ printf(”运算符栈为空!\n”); //栈为空栈得时候返回ERRORreturn ERROR;}while(t!=s、top){ﻩﻩprintf(" %c",*t); //栈不为空得时候依次取出栈内元素t++;ﻩ}return ERROR;}(2)数字栈部分:struct SqStackn//定义数栈{int *base; //栈底指针int*top; //栈顶指针int stacksize; //栈得长度};intInitStackn (SqStackn &s) //建立一个空栈S{s、base=(int*)malloc(50*sizeof(int));if(!s、base)exit(OVERFLOW);//存储分配失败s、top=s、base;s、stacksize=50;return OK;}int GetTopn(SqStackn s,int&e) //数栈取栈顶元素{if(s、top==s、base){printf("运算数栈为空!\n");//栈为空得时候返回ERRORﻩ return ERROR;}elseﻩe=*(s、top-1);//栈不为空得时候,用e作返回值,返回S得栈顶元素,并返回OKreturnOK;}int Pushn(SqStackn &s,int e) //数栈入栈{if(s、top—s、base>=s、stacksize){ﻩﻩprintf("运算数栈满!\n");//栈满得时候,追加5个存储空间ﻩs、base=(int*)realloc (s、base,(s、stacksize+5)*sizeof(int));if(!s、base) exit (OVERFLOW);ﻩs、top=s、base+s、stacksize;//插入元素e为新得栈顶元素s、stacksize+=5;}*(s、top)++=e; //栈顶指针变化returnOK;}int Popn(SqStackn &s,int &e)//数栈出栈{ﻩif (s、top==s、base){ﻩ printf("运算符栈为空!\n");//栈为空栈得视时候,返回ERRORﻩ return ERROR;ﻩ}else{ﻩﻩe=*—-s、top;//栈不空得时候,则删除S得栈顶元素,用e返回其值,并返回OK ﻩreturnOK;}}int StackTraversen(SqStackn &s)//数栈遍历{ﻩint*t;ﻩt=s、base ;ﻩif(s、top==s、base)ﻩ{printf("运算数栈为空!\n”);//栈为空栈得时候返回ERRORﻩ return ERROR;ﻩ}ﻩwhile(t!=s、top)ﻩ{printf(” %d”,*t); //栈不为空得时候依次输出t++;}return ERROR;}五、算法及时间复杂度1、算法:建立两个不同类型得空栈,先把一个‘#’压入运算符栈。

表达式求值算法比较

表达式求值算法比较

在 Pe i e中载入 已截取的 MP rme r V文件 , 将其依次拖 到
时间线上 , 即可实现 多媒 体编辑 。关于 更多的信息, 参考 可
Pe i e的帮助文件及相关 书籍 , rme r 本文 不再过多介绍 。 多媒 体文件在 Pe ir rm e e中编辑后 , 可用 E pr 进行媒 xot
Co a a l t d fEx r sin Ev la in M eh d mp r be S u y o p eso au t t o o
s n  ̄ lQig C e g S u e hn h w i
程书伟
Absr ct Th aerma e n ea o t n o h ufl n rc s frlv n to s o x rsin v lain a d a ay e ta : e p l k 8 a lb r i n t e fl l tp oe s o eea tmeh d fep eso eau to n n lzs a o i me
1表达 式求 值 介绍
目前常用 的表达式种类主 要包括中缀表达式与后缀表 达式两种 。中缀 表达式即平常使用的数学表达式, : x x 如 l3 (+ ) 7 , 5 2 一 特点是符 合人类 的思维习惯 , 用户使 用起来很 顺手 。后缀 表达 式又 称 为逆波 兰式 ,是 波兰 逻辑 学 家 J . L kse i 于 12 u ai c w z 9 9年提 出的另一种表 示表 达式 的方法 , 按 此方法 , 每一运算符都置于其运 算对象之后 , 故称为后缀表 示。 种表示法 的一个特 点是, 这 表达 式中各个运算是按运算
体文件 导出。值得注意 的是导 出要选 择 E p r t D D而 x ot o V

数据结构 实验报告

数据结构 实验报告

数据结构实验报告一、实验目的数据结构是计算机科学中非常重要的一门课程,通过本次实验,旨在加深对常见数据结构(如链表、栈、队列、树、图等)的理解和应用,提高编程能力和解决实际问题的能力。

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

操作系统为 Windows 10。

三、实验内容1、链表的实现与操作创建一个单向链表,并实现插入、删除和遍历节点的功能。

对链表进行排序,如冒泡排序或插入排序。

2、栈和队列的应用用栈实现表达式求值,能够处理加、减、乘、除和括号。

利用队列实现银行排队系统的模拟,包括顾客的到达、服务和离开。

3、二叉树的遍历与操作构建一棵二叉树,并实现前序、中序和后序遍历。

进行二叉树的插入、删除节点操作。

4、图的表示与遍历用邻接矩阵和邻接表两种方式表示图。

实现图的深度优先遍历和广度优先遍历。

四、实验步骤及结果1、链表的实现与操作首先,定义了链表节点的结构体:```cppstruct ListNode {int data;ListNode next;ListNode(int x) : data(x), next(NULL) {}};```插入节点的函数:```cppvoid insertNode(ListNode& head, int val) {ListNode newNode = new ListNode(val);head = newNode;} else {ListNode curr = head;while (curr>next!= NULL) {curr = curr>next;}curr>next = newNode;}}```删除节点的函数:```cppvoid deleteNode(ListNode& head, int val) {if (head == NULL) {return;}ListNode temp = head;head = head>next;delete temp;return;}ListNode curr = head;while (curr>next!= NULL && curr>next>data!= val) {curr = curr>next;}if (curr>next!= NULL) {ListNode temp = curr>next;curr>next = curr>next>next;delete temp;}}```遍历链表的函数:```cppvoid traverseList(ListNode head) {ListNode curr = head;while (curr!= NULL) {std::cout << curr>data <<"";curr = curr>next;}std::cout << std::endl;}```对链表进行冒泡排序的函数:```cppvoid bubbleSortList(ListNode& head) {if (head == NULL || head>next == NULL) {return;}bool swapped;ListNode ptr1;ListNode lptr = NULL;do {swapped = false;ptr1 = head;while (ptr1->next!= lptr) {if (ptr1->data > ptr1->next>data) {int temp = ptr1->data;ptr1->data = ptr1->next>data;ptr1->next>data = temp;swapped = true;}ptr1 = ptr1->next;}lptr = ptr1;} while (swapped);}```测试结果:创建了一个包含 5、3、8、1、4 的链表,经过排序后,输出为 1 3 4 5 8 。

数据结构 3.1栈和队列(顺序及链栈定义和应用)

数据结构 3.1栈和队列(顺序及链栈定义和应用)

假设从终端接受了这样两行字符: whli##ilr#e(s#*s) outcha@putchar(*s=#++);
则实际有效的是下列两行: while (*s) putchar(*s++);
例4:迷宫求解
通常用 “回溯 试探方 法”求 解
##########
# Q # $ $ $ #
#
# #$ $ $ # #
3.1 栈的类型定义
实例引进 考虑问题:一个死胡同,宽度只能够一辆车进 出,现有三辆汽车依次进入胡同停车,后A车 要离开,如何处理? 用计算机模拟以上问题
小花车
小明家 小花家 能能家 点点家 强强家
小花车
点点车 强强车
基本概念
栈(STACK) ——一种限定性的 数据结构,限定只能在表的一端 进行插入和删除的线性表。
# $ $ # #
#
## ##
##
# #
##
# # #
#
## # ## # # #
#
Q #
##########
求迷宫路径算法的基本思想
若当前位置“可通”,则纳入路径,继续( 向东)前进; 若当前位置“不可通”,则后退,换方向 继续探索; 若四周“均无通路”,则将当前位置从路 径中删除出去。
一 顺序栈
顺序栈存储的特点 顺序栈各个基本操作顺序实现 完整的顺序栈c语言程序 模拟停车场
一 顺序栈
存储特点
利用一组地址连续的存储单元依次存放 自栈底到栈顶的数据元素
c语言中可用数组来实现顺序栈
设置栈顶指针Top
elem[arrmax]
a1 a2 a3 a4
Top
top的值
elem[arrmax]

后序遍历二叉树实现表达式求值

后序遍历二叉树实现表达式求值
关键词 :中缀表达式 ; 后序遍历 ;表达式求值 中 图分类号 :T P 3 1 文献标识 码 : A
表达式求值是数据结构 中常见的问题 , 传统的求值方法效率较低. 本文 以逻辑运算为例 , 采用 二叉树 作为表达式的存储结构… , 对二叉树进行后序遍历来实现表达式求值 , 提高了运算效率. 尤其适用于对 同

表 达式 中的变 量赋 予 多组 不 同初值 的情 况 , 比如判 断 表达 式 的 类 型 、 求 解 表 达 式 的成 真 赋值 等 , 从 而 可
扩展 应用 到 逻辑 问题 解决 方 案 的求解 等 领域 中.
1 算法设计
运用 二叉 树 实现 表达 式求 值 需解 决 两 个 大 问题 : 表 达 式 的存 储 与 表 达式 求 值 . 本 文 约定 以逻 辑 运 算 为例 , 分别 用 “ &” 、 “ I ” 、 “一” 表示与、 或、 非 三种 逻辑 运算 . 第一 , 表 达式 存储 算 法设计 . 表 1 算符优先关系表
0 1
0 0
O 1
Байду номын сангаас
为“ 与” 运算的运算规则 , 其他运算类似. ( 2 ) 表达式求值.
求值 过程 中只需建 立一个 存放 操作 数 的栈 即可 . 首先 应 该 明确 一 点 : 在存 储 了表 达式 的二叉 树 中 , 操 作 数都 是 叶子结点 , 运算 符都 是分 支结 点. 后 序遍 历该 二叉 树 , 遵循“ 左~ 右一 中” 的顺 序访 问二叉 树 的各
收 稿 日期 : 2 0 1 4 . 1 1 — 1 3
作 者简介 : 潘风 ( 1 9 8 l 一) , 女, 黑龙 江黑 河人 , 运城学 院计 算机科 学与 技术 系讲师 , 工学 硕士 , 主要 从事 网络技术 及应用 方

表达式求值及符号推导

表达式求值及符号推导

表达式求值及符号推导
本文将围绕表达式的求值及符号推导展开,首先介绍一下表达式求值,表达式求值是一种
数学算法,它通过对一组变量、符号及常量的组合,来求得最终的结果。

表达式可以包含
操作符,如 + 和-,也可以是数学函数,如 sin、cos、tan 和 log。

表达式求值的常见
方法有两种:使用栈的方法或者使用递归的方法。

符号推导就是将状态变量、操作符等符号形式的表达式转化为一个或多个简洁、正确的算
法表达式形式,这就需要我们根据表达式当中的符号、变量等内容进行分析,把表达式转
换为算数表达式供程序进行求值。

这里有两种最基本的推导方法,一是预处理符号表达式,即使用一定规则将表达式转换为更简单的求值格式,这里提到的简化是指转换表达式的方法,而不是算术求值的方法;二是函数代换,函数推导过程通过从表达式当中选出终结符,将它们替换为原子函数,从而得到计算函数。

综上所述,表达式求值是对变量、常量及操作符的一种计算方法,可以使用栈或递归算法
进行,而符号推导则是将不同符号的表达式转换为便于程序计算的算数表达式,多是采用
预处理符号表达式或函数代换的方法,需要我们通过分析推导出适当的算法表达式。

shell脚本四种数值计算方式

shell脚本四种数值计算方式

shell脚本四种数值计算方式在shell脚本中,可以使用四种不同的计算方式来进行数值计算:表达式求值、命令替换、算术运算和高级数学函数。

1.表达式求值:表达式求值是最简单的一种计算方式,只需要将数学表达式放在$(())中。

例如:```result=$(( 5 + 3 ))echo $result```在这个例子中,表达式求值计算了5 + 3,并将结果赋给变量result。

然后,使用echo命令打印出了结果。

2.命令替换:命令替换是一种在数学计算中使用shell命令的方式。

通过将命令放在$(中,shell会先执行该命令,然后将命令的输出结果作为数值计算的一部分。

例如:```result=$(expr 5 + 3)echo $result```在这个例子中,命令替换使用了expr命令来计算5 + 3的结果,并将结果赋给变量result。

然后,使用echo命令打印出了结果。

3.算术运算:除了使用$(( ))和$(进行计算,shell还提供了一些算术运算符来进行数值计算。

例如:```result=`expr 5 + 3`echo $result```在这个例子中,使用了expr命令和反引号(``)来执行数学计算。

结果与前两种方式相同。

4.高级数学函数:在shell脚本中,可以使用数学函数来执行更复杂的数值计算。

有一些内置的数学函数,如sqrt、sin、cos等,可以通过shell的数学库调用。

例如:```result=$(echo "sqrt(4)" , bc -l)echo $result```在这个例子中,先使用echo命令将数学表达式"sqrt(4)"输出给bc 命令,bc命令会执行计算并将结果输出。

然后,命令替换将结果赋给变量result,并使用echo命令打印出了结果。

总结:以上是四种常用的shell脚本中进行数值计算的方式。

表达式求值、命令替换和算术运算是最常见的方式,适合于简单的数学计算。

栈的应用——表达式求值

栈的应用——表达式求值

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

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

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

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

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

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

表达式求值的代码如下:#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;} 为了⽅便起见,本⽂只是简单的设计了⼀个针对⼀位整数的四则运算进⾏求值的算法,对于处理多位整数的四则运算,需要对本⽂接受输⼊的数据类型进⾏“升阶”,把字符数组换成字符串数组,将⼀个整数的多位数字存⼊⼀个字符串进⾏处理。

西华大学数据结构综合期未试题

西华大学数据结构综合期未试题

D.数据对象
2、下列选项中哪个不属于算法重要特性?( D )
A.有穷性和确定性 B.可行性 C.输入和输出 D.可视化和模块

2、算法的效率一般是指( A )。
A.算法的执行时间 B.算法所需要存储空间 C.算法的可读性 D.算法处
理的数据量
3、如一个线性表中的数据元素是由若干个数据项组成,人们通常把这
A.便于随机存取
B.花费的存储空间比顺序表少
C.便于插入与删除
D.数据元素的物理顺序与逻辑顺序不一
定相同
5、下列关于栈说法正确的是( A )。
A. 栈是限定在表尾部进行插入和删除操作的线性表 B . 一般使用链
作栈存储结构,不可使用数组 C. 栈是先进先出的一种结构 D. 栈有栈顶
和栈底,可从栈顶或栈底开始取元素
C. R={<ai,ai+1> |ai,an∈D,i=1,2…,n}
D.
R={<ai-1,ai>
|ai,an∈D,i=2,3…,n-1}
4、与数组相比,用链表表示线性表的主要优点是 ( C )。
A.便于随机存取
B.花费的存储空间比顺序表少
C.便于插入与删除
D.数据元素的物理顺序与逻辑顺序相同
4、与链表相比,采用数组表示性线表的主要优点是( A )。
B. 空串和空格串是同一个概

C. 串的堆分配存储表示中,存储单元是在程序执行之前分配好的
D. 模式串中的每个字符必须与依次和主串中的一个连续字符序列
相等才叫模式匹配成功
9、若已知一棵二叉树先序序列为ABCDEFG,中序序列为CBDAEGF, 则其后序序列为( ) 。
A. BCDAGFE B. CDBFGEA C. CDBAGFE D. CDBGFEA 9、若度为m的广义哈夫曼树中,总叶子个数为n,其非叶子结点的个数 有( A )个。

中缀表达式计算、

中缀表达式计算、

中缀表达式计算、(实用版)目录1.中缀表达式的概念2.中缀表达式的计算方法3.中缀表达式的应用实例正文一、中缀表达式的概念中缀表达式(Infix Expression),又称作中缀代数表示,是一种将运算符和操作数混合排列的表达式。

它是一种用于表示算术运算的记法,其中运算符出现在操作数之间。

与常见的前缀表达式(Postfix Expression)和后缀表达式(Reverse Polish Notation,简称 RPN)不同,中缀表达式的运算顺序取决于运算符的优先级和结合性。

二、中缀表达式的计算方法中缀表达式的计算过程需要通过一定的转换将其转换为可以被计算机直接执行的形式。

常见的计算方法有以下两种:1.栈算法栈算法是一种基于栈的数据结构,可以用来解决中缀表达式的计算问题。

该算法的基本思想是使用一个栈来存储中缀表达式中的操作数,当遇到运算符时,根据栈顶元素的类型进行相应的操作。

具体来说,可以将中缀表达式转换为后缀表达式,然后使用栈来计算后缀表达式的值。

2.直接计算法直接计算法是一种直接根据运算符的优先级和结合性计算中缀表达式的值的方法。

该方法需要先确定运算符的优先级,然后从左到右扫描表达式,根据优先级和结合性进行相应的计算。

这种方法相对简单,但对于复杂的表达式计算效率较低。

三、中缀表达式的应用实例中缀表达式在计算机科学中有广泛的应用,例如:1.表达式求值:通过中缀表达式计算方法,可以实现对复杂数学表达式的求值。

2.编译器:编译器在将高级编程语言转换为机器语言时,需要对表达式进行求值。

中缀表达式作为一种表达式表示方法,可以在编译器中得到应用。

3.数据库查询:在数据库查询中,常常需要对查询条件进行复杂的逻辑运算。

中缀表达式作为一种表达式表示方法,可以帮助用户更方便地表示查询条件。

总结:中缀表达式作为一种表达式表示方法,在计算机科学中有广泛的应用。

算术表达式求值实验报告

算术表达式求值实验报告

算术表达式求值实验报告1. 背景算术表达式求值是计算机科学中的基本问题之一,涉及到对数学表达式的解析和计算。

在计算机编程中,经常需要对用户输入的数学表达式进行求值,以得到正确的计算结果。

因此,研究如何高效地求解算术表达式是非常重要的。

在本次实验中,我们将探索不同方法来求解算术表达式,并比较它们的性能和准确性。

我们将使用Python语言作为实现工具,并通过编写代码来实现不同方法。

2. 分析2.1 表达式解析在进行表达式求值之前,我们首先需要对输入的数学表达式进行解析。

解析过程主要包括以下几个步骤:1.去除空格:将输入的字符串中的空格字符去除。

2.分词:将字符串按照运算符和操作数进行分割,得到一个由标记组成的列表。

3.构建语法树:根据分词结果构建一个语法树,用于表示数学表达式的结构。

4.求值:通过遍历语法树并执行相应操作,最终得到表达式的值。

2.2 求值方法在本次实验中,我们将尝试以下两种不同的求值方法:1.递归求值:通过递归地遍历语法树来求解表达式。

递归求值的优点是简单易懂,但可能存在性能问题。

2.栈求值:使用栈数据结构来辅助求解表达式。

栈可以有效地处理运算符的优先级和括号的匹配问题。

2.3 性能评估为了评估不同方法的性能,我们将使用一组测试用例来对其进行比较。

测试用例包括不同长度和复杂度的数学表达式,以及各种运算符和括号的组合。

我们将使用Python内置的time模块来测量每种方法的执行时间,并比较它们之间的差异。

此外,我们还将检查每种方法是否能正确地计算出表达式的结果。

3. 实验结果3.1 表达式解析在实现表达式解析过程时,我们首先去除输入字符串中的空格,并将其转换为一个字符列表。

然后,我们使用递归下降法来构建语法树。

具体而言,我们定义了以下几个函数:1.parse_expression(tokens):该函数接受一个标记列表作为参数,并返回一个表示整个表达式的语法树。

2.parse_term(tokens):该函数接受一个标记列表作为参数,并返回一个表示项的语法树。

stack方法(一)

stack方法(一)

stack方法(一)Stack 数据结构介绍什么是 Stack?Stack(栈)是一种常见的数据结构,它按照后进先出(LIFO)的原则管理数据。

在 Stack 中,元素只能在栈的顶部进行插入和删除操作,这也是其与队列的最大区别之一。

Stack 的操作Stack 主要包含以下几种操作:•push(item): 将元素item插入栈的顶部。

•pop(): 删除并返回栈顶部的元素。

•peek(): 返回栈顶部的元素,但不对栈进行修改。

•isEmpty(): 检查栈是否为空。

•size(): 返回栈中元素的个数。

Stack 的实现方法Stack 可以用多种方式来实现,下面是常见的两种方法:1.使用数组实现 Stack:class Stack:def __init__(self):self.stack = []def push(self, item):self.stack.append(item)def pop(self):if not self.isEmpty():return self.stack.pop()def peek(self):if not self.isEmpty():return self.stack[-1]def isEmpty(self):return len(self.stack) == 0def size(self):return len(self.stack)2.使用链表实现 Stack:class Node:def __init__(self, data):self.data = dataself.next = Noneclass Stack:def __init__(self):self.head = Nonedef push(self, item):new_node = Node(item)new_node.next = self.headself.head = new_nodedef pop(self):if not self.isEmpty():temp = self.headself.head = self.head.next return temp.datadef peek(self):if not self.isEmpty():return self.head.datadef isEmpty(self):return self.head is Nonedef size(self):count = 0current = self.headwhile current:count += 1current = current.nextreturn countStack 的应用场景Stack 在计算机科学中有许多应用场景,下面是其中的几个例子:•表达式求值:Stack 可以用来实现对中缀表达式求值的算法,如将中缀表达式转换为后缀表达式,再利用后缀表达式求值的方法来计算表达式的结果。

stack的top函数

stack的top函数

Stack的top函数1. 定义在计算机科学中,栈(Stack)是一种常见的数据结构,它是一种只允许在一端进行插入和删除操作的线性表。

栈的特点是“先进后出”(Last In First Out,LIFO),即最后插入的元素最先被删除。

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

其中,栈的top函数是用来获取栈顶元素的函数。

2. 用途栈的top函数用于获取栈顶元素,也就是栈中最后一个插入的元素。

这个函数在许多算法和应用中都有着重要的作用。

以下是一些使用栈的场景:2.1 表达式求值在编写计算器程序时,通常需要对表达式进行求值。

例如,要计算一个包含加减乘除运算符的表达式,可以利用栈来实现。

首先,我们将表达式拆分成操作数和运算符,并按照一定的规则进行入栈操作。

然后,通过判断运算符的优先级,不断弹出栈顶的运算符和操作数,进行计算,并将结果重新入栈,直到整个表达式求解完毕。

最后,栈顶的元素就是表达式的计算结果。

在这个求值过程中,top函数被用来获取栈顶的运算符或操作数。

2.2 函数调用在程序中,函数调用是通过栈来实现的。

当一个函数被调用时,会将函数的返回地址、参数和局部变量等信息保存在栈中。

函数调用栈遵循“先进后出”的原则,即最后调用的函数最先返回。

当函数调用结束后,通过top函数可以获取返回地址,从而返回到调用函数的位置。

2.3 括号匹配在编写编译器或解析器时,需要检查代码中的括号是否匹配。

例如,括号包括圆括号”()“、方括号”[]“和花括号”{}“。

利用栈的特性,可以通过遍历代码中的字符,将左括号入栈,当遇到右括号时,通过top函数获取栈顶的左括号,判断是否匹配。

如果匹配,则将栈顶的左括号弹出,继续遍历下一个字符;如果不匹配,则表示括号不匹配,可以立即返回错误。

3. 工作方式栈的top函数是一个简单的访问函数,用于获取栈顶元素。

它的工作方式如下:1.检查栈是否为空。

如果栈为空,则无法获取栈顶元素,通常会抛出异常或返回错误。

堆栈应用实验报告

堆栈应用实验报告

堆栈应用实验报告一、实验目的本实验主要是通过堆栈的实际应用来进一步深入了解堆栈的概念、原理和使用方法,并学会基于堆栈的算法设计和编程。

二、实验器材1.计算机本身及编程环境。

2.编程软件:Visual Studio 2010(或以上版本)。

三、实验内容及要求1.堆栈的定义与基本操作。

2.堆栈的应用。

(1)逆波兰表达式求值。

(2)括号匹配。

四、实验原理堆栈是一种先进后出的数据结构,常见的基本操作包括以下几个:入栈(Push),将元素添加到堆栈的上方。

出栈(Pop),弹出并返回堆栈的顶部元素。

判空(Empty),判断堆栈是否为空。

堆栈的数据结构通常有两种实现方法:数组实现链表实现逆波兰表达式(Reverse Polish Notation)是一种后缀表达式,其中操作符写在操作数的后面,例如,“1 2 +”等价于中缀表达式“1 + 2”。

使用堆栈可以方便的求解逆波兰表达式,步骤如下:遍历逆波兰表达式,遇到操作数则入栈。

遇到操作符时,弹出栈顶两个元素,进行运算,并将结果入栈。

将最终结果从栈中弹出。

括号匹配问题是指给定一个字符串,判断其中的括号是否成对出现,且出现顺序正确,例如“()”,“(())”等都属于匹配的情况,但“([)]”不匹配。

遍历字符串,遇到左括号则入栈。

遇到右括号时,弹出栈顶元素进行匹配,如果匹配成功则继续遍历,否则直接返回不匹配。

遍历完成后,若堆栈为空,则返回匹配,否则返回不匹配。

五、实验过程```c++#include<iostream>using namespace std;const int MAXN = 10001;int stk[MAXN], top;struct node {char data;node* next;};node* stk;void pop() {if (empty()) return;node* p = stk;stk = stk->next;delete p;}bool empty() {return top == 0;}bool match(char a, char b) {if (a == '(' && b == ')') return true;if (a == '[' && b == ']') return true;if (a == '{' && b == '}') return true;return false;}六、实验结果输入:"5 1 2 + 4 * + 3 -"输出:"14"七、实验心得对于入门学习堆栈的同学来说,可以先尝试使用基本数据结构(数组或链表)实现堆栈,并完成一些简单的堆栈操作。

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

一、设计思想一.中缀式计算结果的设计思想:此种算法最主要是用了两个栈:用两个栈来实现算符优先,一个栈用来保存需要计算的数据numStack(操作数栈),一个用来保存计算优先符priStack(操作符栈)。

从字符串中获取元素,如果是操作数,则直接进操作数栈,但如果获取的是操作符,则要分情况讨论,如下:(这里讨论优先级时暂不包括“(”和“)”的优先级)1.如果获取的操作符a的优先级高于操作符栈栈顶元素b的优先级,则a直接入操作符栈;2.如果获取的操作符a的优先级低于操作符栈栈顶元素b的优先级,则b出栈,a进栈,并且取出操作数栈的栈顶元素m,再取出操作数栈新的栈顶元素n,如果b为+,则用n+m,若为减号,则n-m,依此类推,并将所得结果入操作数栈;3.如果获取的是“(”,则直接进操作符栈;4.如果获取的是“)”,则操作符栈的栈顶元素出栈,做类似于情况2的计算,之后把计算结果入操作数栈,再取操作符栈顶元素,如果不是“(”,则出栈,重复操作,直到操作符栈顶元素为“(”,然后“(”出栈;5.当表达式中的所有元素都入栈后,看操作符栈中是否还有元素,如果有,则做类似于情况2 的计算,并将结果存入操作数栈,则操作数栈中最终的栈顶元素就是所要求的结果。

二.中缀转后缀及对后缀表达式计算的设计思想:中缀转后缀时主要用了一个操作符栈和一个用来存放后缀表达式的栈,从表达式中依次获取元素,如果获取的是操作数,则直接存入s3栈中,如果获取的是操作符也需分情况讨论,如下:(这里讨论优先级时暂不包括“(”和“)”的优先级)1. 如果获取的操作符a的优先级高于操作符栈栈顶元素b的优先级,则a直接入操作符栈;2. 如果获取的操作符a的优先级低于操作符栈栈顶元素b的优先级,则b出栈,a进栈,并且将b存入到操作符栈中;3.如果获取的是“(”,则直接进操作符栈;4.如果获取的是“)”,则操作符栈的栈顶元素出栈,并依次存入到操作符栈中,直到操作符栈栈顶元素为“(”,然后将“(”出栈;5.当表达式中的所有元素都入栈或存入到操作符栈之后,看操作符栈中是否还有元素,如果有,则依次出栈,并且依次存入到操作符栈中,最后打印操作符栈中的字符串,则此字符串即为要求的后缀表达式。

对后缀表达式的计算方法:主要用到了一个操作数栈,从操作符栈中依次取出元素,如果是操作数,则进栈,如果是操作符,则从操作数栈中依次取出两个栈顶元素a1和a2,如果操作符是“/”,则计算a2/a1,将计算结果再次进栈,依此类推,最终栈顶元素即为计算的最终结果。

在这两种算法中,应该特别注意一点:人的习惯,用户在输入表达式时,容易这样输入,如:3*4(3+2),这样是不可取的,应必须要用户输入3*4*(3+2),这是在设计思想上错误提示的很重要一点,否则计算不全面!二、算法流程图第一个图是直接计算的流程图,图中反应除了这种方法的大致设计思路,但是有些细节没有反映出来,比如说,怎样把字符型数据转换为浮点型数据,就没有反映出来。

特别说明的是棱形左边代表Y,右边代表N,具体流程图如下:第二个图是对后缀表达式的求值的算法流程图,同样,棱形左边代表Y,右边代表N,怎样把字符型数据转换为浮点型数据,也同样没有反映出来。

具体图如下:图2 后缀表达式计算的流程图三、源代码程序全部由java语言编写,用面向对象的思路解决,通过eclipe测试。

(一)用中缀式实现四则运算利用栈,进行四则运算的类用两个栈来实现算符优先,一个栈用来保存需要计算的数据numStack,一个用来保存计算优先符priStack。

基本算法实现思路为:用当前取得的运算符与priStack栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算;若小于,则同理,取出栈顶元素运算,将结果入操作数栈。

各个优先级'(' > '*' = '/' >'+' = '-' > ')' 。

package .xiaoliu.zhongzhuishi;import java.util.Stack;//这个算法的表达式要以#结束如:21+5*1#public class Operate {private Stack<Character> priStack = new Stack<Character>();// 操作符栈private Stack<Integer> numStack = new Stack<Integer>();;// 操作数栈/*** 传入需要解析的字符串,返回计算结果(此处因为时间问题,省略合法性验证)* @param str 需要进行技术的表达式* @return 计算结果*/public int caculate(String str) {// 1.判断string当中有没有非法字符String temp;// 用来临时存放读取的字符// 2.循环开始解析字符串,当字符串解析完,且符号栈为空时,则计算完成StringBuffer tempNum = new StringBuffer();// 用来临时存放数字字符串(当为多位数时)StringBuffer string = new StringBuffer().append(str);// 用来保存,提高效率while (string.length() != 0) {temp = string.substring(0, 1);string.delete(0, 1);// 判断temp,当temp为操作符时if (!isNum(temp)) {// 1.此时的tempNum内即为需要操作的数,取出数,压栈,并且清空tempNumif (!"".equals(tempNum.toString())) {// 当表达式的第一个符号为括号int num = Integer.parseInt(tempNum.toString());numStack.push(num);tempNum.delete(0, tempNum.length());}// 用当前取得的运算符与栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算;// 若小于,则同理,取出栈顶元素运算,将结果入操作数栈。

// 判断当前运算符与栈顶元素优先级,取出元素,进行计算(因为优先级可能小于栈顶元素,还小于第二个元素等等,需要用循环判断)while (!compare(temp.charAt(0)) && (!priStack.empty())) {int a = (int) numStack.pop();// 第二个运算数int b = (int) numStack.pop();// 第一个运算数char ope = priStack.pop();int result = 0;// 运算结果switch (ope) {// 如果是加号或者减号,则case '+':result = b + a;// 将操作结果放入操作数栈numStack.push(result);break;case '-':result = b - a;// 将操作结果放入操作数栈numStack.push(result);break;case '*':result = b * a;// 将操作结果放入操作数栈numStack.push(result);break;case '/':result = b / a;// 将操作结果放入操作数栈numStack.push(result);break;}}// 判断当前运算符与栈顶元素优先级,如果高,或者低于平,计算完后,将当前操作符号,放入操作符栈if (temp.charAt(0) != '#') {priStack.push(new Character(temp.charAt(0)));if (temp.charAt(0) == ')') {// 当栈顶为'(',而当前元素为')'时,则是括号内以算完,去掉括号priStack.pop();priStack.pop();}}} else// 当为非操作符时(数字)tempNum = tempNum.append(temp);// 将读到的这一位数接到以读出的数后(当不是个位数的时候)}return numStack.pop();}/*** 判断传入的字符是不是0-9的数字** @param str* 传入的字符串* @return*/private boolean isNum(String temp) {return temp.matches("[0-9]");}/*** 比较当前操作符与栈顶元素操作符优先级,如果比栈顶元素优先级高,则返回true,否则返回false** @param str 需要进行比较的字符* @return 比较结果true代表比栈顶元素优先级高,false代表比栈顶元素优先级低*/private boolean compare(char str) {if (priStack.empty()) {// 当为空时,显然当前优先级最低,返回高return true;}char last = (char) stElement();// 如果栈顶为'('显然,优先级最低,')'不可能为栈顶。

if (last == '(') {return true;}switch (str) {case '#':return false;// 结束符case '(':// '('优先级最高,显然返回truereturn true;case ')':// ')'优先级最低,return false;case '*': {// '*/'优先级只比'+-'高if (last == '+' || last == '-')return true;elsereturn false;}case '/': {if (last == '+' || last == '-')return true;elsereturn false;}// '+-'为最低,一直返回falsecase '+':return false;case '-':return false;}return true;}public static void main(String args[]) {Operate operate = new Operate();System.out.println("the answer is:");int t = operate.caculate("21+5*1#");System.out.println(t);}}(二)用后缀式实现四则运算同样用java语言编写,通过eclipse测试。

相关文档
最新文档