`
duanhengbin
  • 浏览: 384673 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

逆波兰表达式实现表达式计算

    博客分类:
  • Java
 
阅读更多

一年多未更新博客了,此贴纯刷屏用。前段做培训留的题目,自己作了下,感觉蛮简单的代码测的时候还是有不少坑,只做了整数版本,懒得再弄了。

import java.util.ArrayList;
import java.util.Stack;

/**
 * 逆波兰表达式实现四则运算
 *
 * @author Duanhengbin
 *
 */
public class Exercise02 {

	// 四则运算式中的符号
	static String OPERATORS = "+-*/()";

	/**
	 * 根据输入的中缀表达式列表计算
	 * 
	 * @param aPstfix
	 * @return
	 */
	public static int RpnComputer(String expression) {
		Stack<String> stack = new Stack<String>();
		int num1, num2, result;
		num1 = num2 = result = 0;
		ArrayList<String> aPstfix = createPstfix(expression);
		for (String cell : aPstfix) {
			// 数字的场合
			if (OPERATORS.indexOf(cell) == -1) {
				stack.push(cell);
				// 符号的场合
			} else {
				// TODO: 支持带小数的数字计算
				num1 = Integer.parseInt(stack.pop());
				num2 = Integer.parseInt(stack.pop());
				switch (cell) {
				case "+":
					result = num2 + num1;
					break;
				case "-":
					result = num2 - num1;
					break;
				case "*":
					result = num2 * num1;
					break;
				case "/":
					result = num2 / num1;
					break;
				default:
					// TODO: throw Exception
				}
				stack.push(Integer.toString(result));
			}
		}
		return result;
	}

	/**
	 * 根据输入表达式字符串生成后缀表达式列表
	 * 
	 * @param s
	 * @return
	 */
	private static ArrayList<String> createPstfix(String s) {
		String[] cells = extractArrayFromExp(s);
		ArrayList<String> results = new ArrayList<String>();
		Stack<String> stack = new Stack<String>();
		for (String cell : cells) {

			if (OPERATORS.indexOf(cell) == -1) { // 数字的场合
				results.add(cell);

			} else { // 符号的场合
				if (cell.equals(")")) {
					// 待入栈“)”时,只出不入
					results.addAll(popStack(stack, cell));
				} else if (stack.isEmpty() || stack.peek().equals("(") || cell.equals("(") || "*/".contains(cell) && "+-".contains(stack.peek())) {
					// 这些为只入不出的情况
					stack.push(cell);
				} else {
					// 其他情况 先出后入
					if ("*/".contains(cell)) {
						results.add(stack.pop());
					} else {
						results.addAll(popStack(stack, cell));
					}
					stack.push(cell);
				}
			}
		}
		if (!stack.isEmpty()) {
			results.addAll(popStack(stack, ""));
		}
		return results;
	}

	/**
	 * 返回从当前栈中出栈且需要加入到表达式的符号列表
	 * 
	 * @param stack
	 * @return
	 */
	private static ArrayList<String> popStack(Stack<String> stack, String inSign) {
		ArrayList<String> rtn = new ArrayList<String>();
		// 将遇到“(”为止所有符号出栈
		while (!stack.isEmpty() && !"(".equals(stack.peek())) {
			rtn.add(stack.pop());
		}
		// 入栈“)”时,将“(”出栈
		if (inSign.equals(")")) {
			stack.pop();
		}
		return rtn;
	}

	/**
	 * 先将符号两侧增加空格,再替换多个空格为一个空格,最后用空格切分,将表达式拆分成数字与符号列表
	 * 
	 * @param s
	 * @return
	 */
	private static String[] extractArrayFromExp(String s) {
		String sOperator = null;
		// 在符号前后添加空格
		for (int i = 0; i < OPERATORS.length(); i++) {
			sOperator = OPERATORS.substring(i, i + 1);
			s = s.replaceAll("\\" + sOperator, " " + sOperator + " ");
		}
		// 将多个空白字符:[\t\n\x0B\f\r] 替换为一个空格 注意这里正则简记法\s
		s = s.replaceAll("[\\s]+", " ");
		return s.trim().split(" ");
	}
}

 测试代码

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import exercise.Exercise02;

@RunWith(Parameterized.class)
public class Exercise02Test {

	private String exep;
	private String result; 
	
	@Parameters 
	public static Collection<String[]> data()    { 
		return Arrays.asList(new String[][]   { 
			{ "9   +  	(3	-1)*  3+10/2 ", "20" },
			{ "((((2-3)*(8/2-1))))", "-3" },
			{ "((1+2+3) *  2)-10+4/2*3 ", "8" }, 
			{ "(1+2+3+4*5*6/2-9)", "57" },
			{ " (1*2*3*8-5*6/2/3/5-9)", "38" },
			{ " (1*2*3*6/9/2*10-(1+2)*4) ", "8" },
			{ "10-9/3+3*(2/(1/1))", "13" }
		}); 
	}	
	
	public Exercise02Test(String exep, String result)    { 
		this.exep = exep; 
		this.result = result; 
	} 
	
	@Test
	public void testRpnComputer() {
		assertEquals(result, String.valueOf(Exercise02.RpnComputer(exep)));
	}
}

 

分享到:
评论

相关推荐

    逆波兰表达式实现

    逆波兰表达式实现 逆波兰表达式是一种后缀表达式,通常用于表示数学表达式的计算顺序。它的特点是运算符在后面,先计算括号里的运算,然后计算乘除,最后计算加减。逆波兰表达式的实现可以通过栈或队列来实现。 逆...

    基于逆波兰表达式的计算程序

    逆波兰表达式,又称后缀...以上就是基于逆波兰表达式的计算程序相关的核心知识点,涵盖了从表达式转换到求值的整个过程,以及可能的编程实现和应用场景。理解并掌握这些内容,能够帮助我们编写和使用此类计算程序。

    逆波兰表达式及其算法实现

    ### 逆波兰表达式及其算法实现 ...通过合理的算法设计,可以高效地实现逆波兰表达式的转换与计算,从而简化编程过程并提高计算效率。在未来的发展中,逆波兰表达式仍将在多种计算场景中发挥重要作用。

    逆波兰表达式 c语言实现

    在C语言中实现逆波兰表达式的转换通常包括以下步骤: 1. **输入解析**:程序需要读取用户提供的中缀表达式,如"2 + 3 * 4"。这个过程可以通过分隔符(如空格或逗号)将表达式拆分成符号和数字。 2. **优先级判断**...

    利用堆栈实现逆波兰表达式 后缀法

    ### 利用堆栈实现逆波兰表达式(后缀法) #### 一、逆波兰表达式简介 逆波兰表达式,又称后缀...通过本文的介绍,我们不仅了解了逆波兰表达式的概念和计算原理,还学习了一种基本的数据结构——顺序表的实现方法。

    逆波兰表达式的C++实现

    通过这样的实现,我们可以有效地计算逆波兰表达式,不仅简化了表达式的求值过程,还提高了计算效率。逆波兰表达式在编译器设计、计算器程序以及其他需要解析和计算数学表达式的地方都有广泛的应用。

    易语言逆波兰表达式计算

    通过以上步骤,易语言的逆波兰表达式计算源码实现了从输入的逆波兰表达式到计算结果的完整流程。了解这些知识点后,我们可以自己编写类似功能的程序,或者理解并优化现有的源代码。在易语言中,这样的计算功能有助于...

    逆波兰表达式

    在某些复杂的数据结构实现,如二叉树或哈希表中,链表可能会用到,尽管在逆波兰表达式的直接处理中不常见。 总的来说,逆波兰表达式是计算机科学中解决计算问题的一种有效工具,它涉及到的数据结构和算法概念如堆栈...

    用二叉树存储逆波兰表达式

    4. **后序遍历**:后序遍历的顺序是“左-右-根”,对于逆波兰表达式,它会按照正确的计算顺序输出操作数和运算符,非常适合计算。例如,对于我们的表达式,后序遍历结果为 "2 3 + 4 * ",这正是我们计算表达式所需的...

    逆波兰表达式算法_表达式_

    - `ExpressionParserUtil.java` 文件可能包含了逆波兰表达式算法的具体实现,包括一个类`ExpressionParserUtil`,以及可能的解析、计算等方法。 - 类似的方法可能包括 `toPostfixExpression()`(将中缀表达式转换...

    简易灰色逆波兰表达式计算器代码

    - 逆波兰表达式的优点在于其计算效率高,因为不需要处理括号和优先级问题,只需用栈即可完成运算。 - 解析逆波兰表达式通常采用两个栈:一个数值栈用于存储数字,一个运算符栈用于存储运算符。遇到数字时压入数值...

    逆波兰表达式求值源代码

    ### 逆波兰表达式求值的实现 给定的代码片段展示了如何使用栈数据结构来实现逆波兰表达式的求值。栈是一种先进后出(LIFO,Last In First Out)的数据结构,非常适合用于处理逆波兰表达式,因为可以依次处理表达式...

    将一个字符串转换为其逆波兰表达式

    逆波兰表达式,又称后缀表达式,是一种不使用括号的数学表达式表示方法,它使用栈的数据结构来解析和计算表达式。在逆波兰表达式中,运算符位于其操作数之后,使得表达式的解析更为简单。本篇文章将详细讲解如何用...

    用java和逆波兰表达式写的计算器

    4. **后缀表达式计算**:在得到逆波兰表达式后,我们可以通过遍历后缀表达式的每一个元素来计算结果。如果是数字,直接压栈;如果是运算符,就取出栈顶的两个元素进行运算,并将结果压回栈。 5. **异常处理**:在...

    逆波兰表达式计算易语言源码

    5. **资源下载与使用**:提到的资源提供了逆波兰表达式的易语言源码例程,使用者可以通过下载这些资源,学习和理解如何在易语言环境中实现逆波兰表达式的计算。资源作者的信息没有在描述中给出,但通常,这样的资源...

    逆波兰表达式求解的程序(2种方法)

    逆波兰表达式,又称后缀表达式,是一种用于表示数学计算的符号表示法。它将操作符放在操作数之后,避免了使用括号来决定运算的优先级,从而简化了解析过程。本教程将介绍两种在C/C++或Linux环境下求解逆波兰表达式的...

    基于逆波兰表达式的科学计算机源码

    本项目提供了一个基于逆波兰表达式的科学计算器的源码,非常适合学习者深入理解计算原理和编程实现。 首先,我们要了解逆波兰表达式的工作原理。在普通中缀表达式(如2 + 3 * 4)中,运算符位于操作数之间,而在逆...

    中缀表达式转化为逆波兰表达式

    中缀表达式和逆波兰表达式是两种不同的数学表达式表示方式,对于计算和解析有着不同的优势。本文将深入探讨如何将中缀表达式转化为逆波兰表达式,并结合C语言进行实现。 中缀表达式是我们日常生活中最常见的数学...

Global site tag (gtag.js) - Google Analytics