本文主要内容:

  • 表达式的三种形式
  • 中缀表达式与后缀表达式转换算法

一、表达式的三种形式:

  • 中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3。我们从小做数学题时,一直使用的就是中缀表达式。
  • 后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则),如:2 1 + 3 *。又比如3+(6-4/2)*5=23的后缀表达式为:3642/-5*+# (#符号为结束符)
  • 前缀表达式:同后缀表达式一样,不包含括号,运算符放在两个运算对象的前面,如:* + 2 1 3 。前缀表达式和后缀表达式其实是差不多的,只不过符号位置不同而已,前缀表达式不是很常见。

二、中缀表达式转换为后缀表达式:(思路)

1、将中缀表达式转换为后缀表达式:(步骤,有点难理解)

(1)当读到数字直接送至输出队列中;

(2)当读到运算符t时:

  a.将栈中所有优先级高于或等于t的运算符弹出,送到输出队列中;

    注:这句话不好理解,可以说成这样,从栈顶开始,依次弹出比当前处理的运算符优先级高的运算符,直到一个比它优先级低的或者遇到了一个左括号就停止

  b.t进栈;

(3)读到左括号时总是将它压入栈中;

(4)读到右括号时,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号;

(5)中缀表达式全部读完后,若栈中仍有运算符,将其送到输出队列中。

 

举例:

上图中,左侧的那一列为输出序列,右侧的那一列为栈。

2、运用后缀表达式进行计算:

  (1)建立一个栈S;

  (2)从左到右读后缀表达式,读到数字就将它转换为数值压入栈S中,读到运算符则从栈中依次弹出两个数分别到Y和X,然后以“X 运算符 Y”的形式计算机出结果,再压加栈S中;

  (3)如果后缀表达式未读完,就重复上面过程,最后输出栈顶的数值则为结束。

举例:

3+(2-5)*6/3=-3 ,其后缀表达式为:325-6*3/+。其运算结果如下:

三、代码实现:将中缀表达式转换为后缀表达式

  • JDK  Stack类使用
  • 使用泛型

代码实现:

(1)StringToArithmetic.java:(中缀表达式转化为后缀表达式的工具类

 /**
* Created by smyhvae on 2015/9/7.
* 工具类:
* 1、中缀表达式转化为后缀表达式
* 2、给出一个算术表达式(中缀表达式),直接得到计算结果
*/ import java.util.Stack;
import java.util.regex.Pattern; public class StringToArithmetic { private StringToArithmetic() {
} //方法:给出一个算术表达式(中缀表达式),得到计算结果。 例如 (5+8+10)*1,返回23
public static double stringToArithmetic(String string) {
return suffixToArithmetic(infixToSuffix(string));
} /**
* 中缀表达式转后缀表达式 只处理了+,-,*,/和括号,没有处理负号及其它运算符,也没对前缀表达式验证。
* 如要处理负号,可对表达式进行预转义处理,当下面条件成立时,将负号换成单目运算符"!" infix.charAt[i]=='-'&&(
* i==0||infix.charAt[i-1]=='(')
* 3*6/4+3
* 3+6-4 3 6 + 4 -
* 3+(6-4/2)*5 3 6 4 2 / - 5 * +
*/
//方法:中缀表达式转成后缀表达式
public static String infixToSuffix(String infix) {
Stack<Character> stack = new Stack<Character>();
String suffix = "";
int length = infix.length();
for (int i = 0; i < length; i++) {
Character temp;
char c = infix.charAt(i);
switch (c) {
// 忽略空格
case ' ':
break;
// 碰到'(',push到栈
case '(':
stack.push(c);
break;
// 碰到'+''-',将栈中所有运算符弹出,送到输出队列中
case '+':
case '-':
while (stack.size() != 0) {
temp = stack.pop();
if (temp == '(') {
stack.push('(');
break;
}
suffix += " " + temp;
}
stack.push(c);
suffix += " ";
break;
// 碰到'*''/',将栈中所有乘除运算符弹出,送到输出队列中
case '*':
case '/':
while (stack.size() != 0) {
temp = stack.pop();
if (temp == '(' || temp == '+' || temp == '-') {
stack.push(temp);
break;
} else {
suffix += " " + temp;
}
}
stack.push(c);
suffix += " ";
break;
// 碰到右括号,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号
case ')':
while (stack.size() != 0) {
temp = stack.pop();
if (temp == '(')
break;
else
suffix += " " + temp;
}
// suffix += " ";
break;
//如果是数字,直接送至输出序列
default:
suffix += c;
}
} //如果栈不为空,把剩余的运算符依次弹出,送至输出序列。
while (stack.size() != 0) {
suffix += " " + stack.pop();
}
return suffix;
} /**
* postfix
*
* @return double
*/
//方法:通过后缀表达式求出算术结果
public static double suffixToArithmetic(String postfix) { Pattern pattern = Pattern.compile("\\d+||(\\d+\\.\\d+)"); //使用正则表达式 匹配数字
String strings[] = postfix.split(" "); //将字符串转化为字符串数组
for (int i = 0; i < strings.length; i++)
strings[i].trim(); //去掉字符串首尾的空格
Stack<Double> stack = new Stack<Double>(); for (int i = 0; i < strings.length; i++) { if (strings[i].equals(""))
continue; //如果是数字,则进栈
if ((pattern.matcher(strings[i])).matches()) { stack.push(Double.parseDouble(strings[i]));
} else {
//如果是运算符,弹出运算数,计算结果。
double y = stack.pop();
double x = stack.pop();
stack.push(caculate(x, y, strings[i])); //将运算结果重新压入栈。
}
}
return stack.pop(); //弹出栈顶元素就是运算最终结果。 } private static double caculate(double x, double y, String simble) {
if (simble.trim().equals("+"))
return x + y;
if (simble.trim().equals("-"))
return x - y;
if (simble.trim().equals("*"))
return x * y;
if (simble.trim().equals("/"))
return x / y;
return 0;
}
}

(2)Test.java:(测试类)

 public class Test {
public static void main(String[] args) { String str = "3+(2-5)*6/3"; //其后缀表达式为325-6*3/+ //调用方法:中缀表达式转成后缀表达式
System.out.println(StringToArithmetic.infixToSuffix(str)); //调用方法:给出一个算术表达式(中缀表达式),得到计算结果
System.out.println(StringToArithmetic.stringToArithmetic(str)); } }

上方代码中,第07行是根据中缀表达式算出后缀表达式。

第10行:是给出一个中缀表达式,直接的到计算结果,其实它的步骤是:先根据中缀表达式得到后缀表达式,然后根据后缀表达式去计算结果

运行效果:

数据结构Java实现06----中缀表达式转换为后缀表达式的更多相关文章

  1. 利用stack结构,将中缀表达式转换为后缀表达式并求值的算法实现

    #!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving with Algorithms and Da ...

  2. 练习3.20 a 将中缀表达式转换为后缀表达式

    //将中缀表达式转换为后缀表达式 int main() { ; ]={,,,,,,,}; char tmp; PtrToStack s; s = CreateStack( MaxSize ); ) { ...

  3. 栈的应用实例——中缀表达式转换为后缀表达式

    声明:本程序读入一个中缀表达式,将该中缀表达式转换为后缀表达式并输出后缀表达式. 注意:支持+.-.*./.(),并且输入时每输入完一个数字或符号都要加一个空格,特别注意的是在整个表达式输入完成时也要 ...

  4. 中缀表达式转换为后缀表达式(python实现)

    中缀表示式转换为后缀表达式 需要一个存放操作符的栈op_stack,输出结果的列表output 步骤: 从左到右遍历表达式: 1. 若是数字,直接加入到output 2. 若是操作符,比较该操作符和o ...

  5. javascript使用栈结构将中缀表达式转换为后缀表达式并计算值

    1.概念 你可能听说过表达式,a+b,a+b*c这些,但是前缀表达式,前缀记法,中缀表达式,波兰式,后缀表达式,后缀记法,逆波兰式这些都是也是表达式. a+b,a+b*c这些看上去比较正常的是中缀表达 ...

  6. Infix to postfix conversion 中缀表达式转换为后缀表达式

    Conversion Algorithm 1.操作符栈压入"#": 2.依次读入表达式的每个单词: 3.如果是操作数则压入操作数栈: 4.如果是操作符,则将操作符栈顶元素与要读入的 ...

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

    中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操 ...

  8. 中缀表达式转后缀表达式(Java代码实现)

    后缀表达式求值 后缀表达式又叫逆波兰表达式,其求值过程可以用到栈来辅助存储.例如要求值的后缀表达式为:1 2 3 + 4 * + 5 -,则求值过程如下: 遍历表达式,遇到数字时直接入栈,栈结构如下 ...

  9. Java堆栈的应用2----------中缀表达式转为后缀表达式的计算Java实现

    1.堆栈-Stack 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除 ...

随机推荐

  1. H5调用Android播放视频

    webView.loadUrl("http://10.0.2.2:8080/assets/RealNetJSCallJavaActivity.htm"); js调用的Java文件中 ...

  2. mysql=null的优雅解决方法

    对于不是采用所有字段都是not null的mysql表设计而言,mysql提供了一个<=>操作符. 在oracle中我们的处理方式通常类似: where a = #{var} or #{v ...

  3. Windows工作集内存

    Windows任务管理器默认情况下,“内存(私人工作集)”列处于选中状态. 私人工作集是工作集的一个子集,它是描述每个进程所使用的内存数量的技术术语.私人工作集专门描述了某个进程正在使用的且无法与其他 ...

  4. Eclipse反编译工具Jad及插件JadClipse配置

    Jad是一个Java的一个反编译工具,是用命令行执行,和通常JDK自带的java,javac命令是一样的.不过因为是控制台运行,所以用起来不太方便.不过幸好有一个eclipse的插件JadClipse ...

  5. cl_gui_cfw=>flush

       用法一:      REFRESH_TABLE_DISPLAY虽然刷新的界面,但是SAP GUI并不是实时更新,而是将更新的结果放在缓存中,手动调用CL_GUI_CFW=>FLUSH才能触 ...

  6. Opengles 管线编程介绍

      OpenGL ES 2.0可编程管道 上图橙色部分(Vertex Shader和Fragment Shader)为此管道的可编程部分.整个管道包含以下两个规范: 1)         OpenGL ...

  7. 在iOS 8中使用UIAlertController

    iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备尺寸 ...

  8. Android 之 json数据的解析(jsonReader)

    json数据的解析相对而言,还是比较容易的,实现的代码也十分简单.这里用的是jsonReade方法来进行json数据解析. 1.在解析之前,大家需要知道什么是json数据. json数据存储的对象是无 ...

  9. fastCGI与PHP-fpm

    fastCGI是nginx和php之间的一个通信接口,该接口实际处理过程通过启动php-fpm进程来解析php脚本,即php-fpm相当于一个动态应用服务器,从而实现nginx动态解析php.因此,如 ...

  10. Effective Java 45 Minimize the scope of local variables

    Principle The most powerful technique for minimizing the scope of a local variable is to declare it ...