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

  我们平常书写的四则运算表达式属于中缀表达式,形式为"9+(3-1)*3+10/2",因为所有的运算符号都在两操作数之间,所以称为中缀表达式。我们使用中缀表达式来计算表达式的值,不过这种形式并不适合计算机求解。接下来,我们将中缀表达式转化为后缀表达式,所谓的后缀表达式就是操作符位于操作数后面的不包含括号的算数表达式,也叫做逆波兰表达式。

1)首先介绍一种人工的转化方法(http://www.cnblogs.com/MichaelYin/archive/2012/05/02/2479248.html)。以"9+(3-1)*3+10/2"为例,按照运算的规则,找出首先计算的部分,这部分包含两个操作数和一个操作符,将操作符移动到两个操作数右侧,这就完成了第一部分的转换,将这部分看作一个操作数,按照运算规则,以相同的方法转换,转换过程如下:

2)还可以利用二叉树求得后缀表达式,首先利用中缀表达式构造二叉树,数字是叶子节点,操作符为根节点。每次找到“最后计算”的运算符,作为当前根节点,运算符左侧表达式作为左节点,右侧表达式作为右节点,然后递归处理(http://www.xuebuyuan.com/388108.html)。9+(3-1)*3+10/2对应的二叉树的构造过程如下图所示:

  此二叉树做后序遍历就得到了后缀表达式。

3)还可以利用栈来实现中缀表达式转化为后缀表达式。转化方法如下所述:

a.从左向右扫描表达式,如果是数字就输出,否则转b。

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

c.如果扫描的字符或者栈顶元素是“(”,扫描的字符直接入栈。即使扫描的字符是")"也不会入栈,因为如果是")",会出栈至栈顶元素是"("。

d.如果扫描字符是"+"或者"-",则一直出栈至栈顶元素为"+"或者"-"或者"("。如果最终栈顶元素是"(",则扫描操作符直接入栈,否则,弹出栈顶元素,然后扫描的操作符再入栈。

e.如果扫描的操作符是"*"或者"/",如果栈顶元素是同优先级的"*"或者"/",首先将栈顶元素出栈,然后扫描的操作符入栈。否则,直接入栈。

f.扫描完成整个表达式之后,如果栈内还有元素,则依次全部出栈。

  对应的代码如下,首先是栈的定义,然后是reversePlishNotation2转换方法,表达式输入格式为字符串,操作数和运算符以及小括号以空格分隔:

  1 mport java.util.Arrays;
  2 import java.util.HashSet;
  3 import java.util.Random;
  4 import java.util.Set;
  5
  6 /**
  7  * Created by hfz on 2016/7/30.
  8  */
  9 public class Stack_Array implements Stack {
 10     public static int CAPACITY=40;
 11     protected int capacity;
 12     protected int top=-1;
 13     protected Object[] S;
 14     public Stack_Array(int capacity){
 15         this.capacity=capacity;
 16         S=new Object[capacity];
 17     }
 18     public Stack_Array(){
 19         this(CAPACITY);//一般情况下,使用this.方法名调用自身方法,不过在构造方法里可以使用this()的形式调用其他构造函数
 20     }
 21     public void push(Object ele) throws ExceptionStackFull {
 22         if(getSize()==CAPACITY){
 23             throw new ExceptionStackFull("栈溢出!");
 24         }
 25         S[++top]=ele;
 26     }
 27     public Object pop() throws ExceptionStackEmpty{
 28         if(isEmpty()){
 29             throw new ExceptionStackEmpty("栈为空,不能出栈!");
 30         }
 31         Object ele=S[top];
 32         S[top--]=null;
 33         return ele;
 34     }
 35
 36     public Object top() throws ExceptionStackEmpty{
 37         if(isEmpty()){
 38             throw new ExceptionStackEmpty("栈为空,没有栈顶元素!");
 39         }
 40         return S[top];
 41     }
 42     public boolean isEmpty(){
 43         return (top<0);
 44     }
 45     public int getSize(){
 46         return top+1;
 47     }
 48
 49 public static void main(String [] args){
 50         String s="9 + ( 3 - 1 ) * 3 + 10 / 2";
 51         String s1="20 * ( ( 2.44 - 1.8 ) / 0.4 + 0.15 )";
 52
 53         System.out.println(reversePlishNotation2(s));
 54         System.out.println(reversePlishNotation2(s1));
 55         inverseArray();
 56
 57
 58     }
 59
 60 /*
 61     中缀表达式以#作为结束标志,以空格分割各个元素。
 62     中缀表达式转化为后缀表达式(逆波兰表达式)的方法
 63     1.从左向右扫描中缀表达式,遇到数字就直接输出。遇到运算符,如果其优先级高于栈顶元素或栈为空,入栈。如果低于栈顶
 64     元素优先级,则栈顶元素出栈输出,一直到栈顶元素的优先级低于或等于此运算符。如果两个运算符优先级相同的话,弹出栈顶元素,然后再将运算符入栈。
 65
 66     2.对于小括号做另外处理,如果是左括号“(”,直接入栈。右括号")"的话,栈顶元素出栈输出,一直到栈顶元素为“(”,将“(”出栈
 67     ,不过并不输出。右括号“)”并不入栈,直接丢弃。
 68     3.扫描完成之后,如果栈中还有元素,依次输出。
 69      */
 70     public static String reversePlishNotation2(String str){
 71         Stack_Array notationStack = new Stack_Array();
 72         String[] expressionString=str.split(" ");
 73         int expressionLength = expressionString.length;
 74         String currentString = "0";
 75         StringBuilder sb = new StringBuilder();
 76         Set<String> notationSet=new HashSet<>();
 77         notationSet.add("+");
 78         notationSet.add("-");
 79         notationSet.add("*");
 80         notationSet.add("/");
 81         notationSet.add("(");
 82         notationSet.add(")");
 83         String topElement="null";
 84         for (int i = 0; i <expressionLength ; i++) {
 85             currentString=expressionString[i];
 86             if(!notationSet.contains(currentString)){
 87              sb.append(currentString).append(" ");
 88             }
 89             else{//不是数字,而是操作符
 90                 try{
 91                     topElement=(String)notationStack.top();
 92                 }
 93                 catch (ExceptionStackEmpty ex){
 94                     notationStack.push(currentString);
 95                     continue;
 96                 }
 97                 if(currentString.equals(")")){//当前扫描的字符是")",则操作符出栈至栈顶元素是"(",同时添加操作符,最后删除"("。
 98                     while(!topElement.equals("(")) {
 99                         sb.append(topElement).append(" ");
100                         try {
101                             notationStack.pop();
102                             topElement = (String) notationStack.top();
103                         }
104                         catch (ExceptionStackEmpty ex){
105                             break;
106                         }
107                     }
108                     if(topElement.equals("(")){
109                         notationStack.pop();
110                     }
111                 }
112                 else if(currentString.equals("(")||topElement.equals("(")){//如果扫描字符或者栈顶字符是"(",则扫描字符直接入栈。
113                 // 即使扫描字符是")"也不会入栈,因为上面一层的判断条件,要求出栈至"("。
114                     notationStack.push(currentString);
115                 }
116                 else if(currentString.equals("+")||currentString.equals("-")){
117                     //如果扫描字符是"+"或者"-",则一直出栈至栈顶元素为"+"或者"-"或者"("。如果最终栈顶元素是"(",则扫描操作符直接入栈,否则,弹出栈顶
118                     //元素,然后扫描的操作符再入栈。
119                     while (!topElement.equals("+")&&!topElement.equals("-")&&!topElement.equals("(")){
120                         sb.append(topElement).append(" ");
121                         try{
122                             notationStack.pop();
123                             topElement=(String)notationStack.top();
124                         }
125                         catch (ExceptionStackEmpty ex){
126                             break;
127                         }
128                     }
129                     if(topElement.equals("+")||topElement.equals("-")){
130                         sb.append((String)notationStack.pop()).append(" ");
131                     }
132                     notationStack.push(currentString);
133                 }
134                 else if(currentString.equals("*")||currentString.equals("/")){
135                     //如果扫描的操作符是"*"或者"/",如果栈顶元素是同优先级的"*"或者"/",首先将栈顶元素出栈,然后扫描的操作符入栈。否则,直接入栈。
136                     if(topElement.equals("*")||topElement.equals("/")){
137                         sb.append((String) notationStack.pop()).append(" ");
138                     }
139                     notationStack.push(currentString);
140                 }
141             }
142         }
143         //扫描完成整个表达式之后,如果栈内还有元素,则依次全部出栈。
144         while (!notationStack.isEmpty()){
145             sb.append(notationStack.pop()).append(" ");
146         }
147         return sb.toString();
148     }
149
150
151 }
152 class ExceptionStackFull extends RuntimeException{
153     public ExceptionStackFull(String err){
154         super(err);
155     }
156 }

  

时间: 2024-10-25 00:46:53

中缀表达式转后缀表达式---栈--二叉树---四则运算的相关文章

数据结构——栈——中缀表达式和后缀表达式

什么是中缀表达式,什么是后缀表达式 我们一般看见的多项式计算都是中缀表达式构成的:1+2*3+4/3 类似这种,为什么说是中缀呢?因为它的计算符号都是在两个数中间的. 那么自然而然的明白了后缀表达式是一种计算符号在两个数后面的. 如123*+43/+ 中缀表达式和后缀表达式有什么关系? 其实仔细你就会发现,上面给出的式子其实都是一样的,只是计算的顺序在后缀表达式中你看不懂而已. 因为我们习惯去看中缀表达式的计算. 其实他们之间是可以互相转换的.他们也可以表达同一个意思,同一个计算式子. 为什么会

栈的应用之中缀表达式转后缀表达式

1,中缀表达式的定义及为什么要将中缀表达式转换为后缀表达式? 中缀表达式(中缀记法) 中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间.中缀表达式是人们常用的算术表示方法. 虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值.对计算机来说,计算前缀或后缀表达式的值要比中缀表达式简单. 比如,计算机计算后缀表达式的过程如下----后缀表达式的计算机求值: 从左

将中缀表达式转换为后缀表达式,然后利用栈对表达式求值。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js.js"></script> </head> <body> 输入中缀表达式空格分隔 例如 2 + 3 <input type=

栈的应用:中缀表达式转为后缀表达式

1.中缀表达式转为后缀表达式 规则:(栈实现) 1)如果遇到操作数,我们就直接将其输出. 2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中. 3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止.注意,左括号只弹出并不输出. 4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止.弹出完这些元素后,才将遇到的操作符压入到栈中.有一点需要注意,只有在遇到" ) "的情况下

Python与数据结构[1] -&gt; 栈/Stack[1] -&gt; 中缀表达式与后缀表达式的转换和计算

中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操作数(数字/字母等),则加入后缀表达式中 若元素为操作符,则压入栈中,此时对比入栈操作符与栈内元素的计算等级,等级大于或等于入栈元素的栈内操作符都将被弹出栈,加入到后缀表达式中 左括号直接入栈,优先级最高,不弹出栈内元素 右括号不入栈,而是弹出所有元素加入后缀表达式,直至遇见匹配的左括号,并弹出左括

java中缀表达式转后缀表达式

四则运算是栈的重要应用之一 中缀表达式转后缀表达式(逆波兰算法)过程 从左到右遍历中缀表达式 数字直接输出为后缀表达式一部分 如果是符号,则判断与栈顶元素的优先级 高于栈顶元素优先级直接入栈 低于或等于栈顶优先级栈顶元素出栈并输出为后缀表达式一部分(注意这里是递归比较栈顶元素的优先级并出栈),最后将当前元素入栈直到遍历完中缀表达式,最终输出后缀表达式 下面是自己的实现源码 package com.yhq.demospringboot; import org.apache.commons.lang

计算器核心算法——中缀表达式转为后缀表达式

中缀表达式转后缀表达式的过程类似编译过程——四则运算表达式中的括号必须匹配——根据运算符优先级进行转换——转换后的表达式中没有括号——转换后可以顺序的计算出最终结果 这是某位伟人研究出的算法,在这里我们直接拿来用就可以. 转换过程:——当前元素e为数字:输出——当前元素e为运算符:1.与栈顶运算符进行优先级比较2.小于等于:将栈顶元素输出,转13.大于:将当前元素e入栈 ——当前元素e为左括号:入栈——当前元素e为右括号:1.弹出栈顶元素并输出,直至栈顶元素为左括号2.将栈顶的左括号从栈中弹出

中缀表达式转为后缀表达式

** * 中缀表达式转后缀表达式 * * 作用:将一长串计算表达式转换为计算机易于操作的字符序列,用于计算器的设计 *  * 参与转换运算符 * +-/*()^% * * * 使用StringBuilder来保存转换出的后缀表达式 * 使用栈来操作运算符 * * * 转换原则 * 1.上述字符中()没有优先级值,+-优先级值为1,/*%优先级值为2,^优先级值为3 * 2.对于一个待计算的表达式,从左向右逐个检查每个字符 * 3.遇到数字,直接append到StringBuilder * 4.遇

ZH奶酪:Python 中缀表达式转换后缀表达式

实现一个可以处理加减乘数运算的中缀表达式转换后缀表达式的程序: 一个输入中缀表达式inOrder 一个输出池pool 一个缓存栈stack 从前至后逐字读取inOrder 首先看一下不包含括号的: (1)操作数:直接输出到pool (2)操作符:判断当前操作符与stack[top]操作符的优先级 <1>当前操作符优先级高于stack[top]:将当前操作符添加到stack中: <2>当前操作符优先级低于或等于stack[top]:从stack[top]开始出栈,直到stack[to

经典白话算法之中缀表达式和后缀表达式

一.后缀表达式求值 后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储. 假定待求值的后缀表达式为:6  5  2  3  + 8 * + 3  +  *,则其求值过程如下: (1)遍历表达式,遇到的数字首先放入栈中,依次读入6 5 2 3 此时栈如下所示: (2)接着读到"+",则从栈中弹出3和2,执行3+2,计算结果等于5,并将5压入到栈中. (3)然后读到8(数字入栈),将其直接放入栈中. (4)读到"*",弹出8和5,执行8*5,并将结果40压入栈中