`
ljl_ss
  • 浏览: 54804 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

java实现逆波兰式的转化并计算结果

阅读更多
1.将中缀表达式转化为逆波兰式的思路,如将1+2转化为12+:
    定义一个stringbuffer来存放后缀式,并定义一栈stack
 
  loop:读取读取输入的字符串,将当前读入的字符记为a:
      step1:如果a为操作数则直接append到stringbuffer中.
     step2:如果a为左括号“(”则将a进栈
      step3:如果a为右括号,则从栈顶开始找,并移动栈顶指针,如果当前栈顶元素非左括号则将栈顶元素append到stringbuffer中,直到找到第一个左括号,找到后将左括号出栈,并注意不要将左括号放到stringbuffer中.
     step4:如果a为运算符,则取栈顶元素和a进行比较如果栈顶元素的运算符优先级小于a则将a入栈,否则将栈顶弹出存到stringbuffer中,直到栈顶元素的运算符优先级小于a为址,注左括号和右括号的运算优先级比+-*/都低在这里
end loop;

    最后将stringbuffer进行toString并拼上stack中的元素就得到后缀表达式


2.计算逆波兰式的思路
  
 定义一栈 stack:
  输入一段后缀表达式如12+:
  loop:逐个读取字符串中的字符记为b:
  1.如果a为操作数,则入栈
  2.如果a为操作符,则弹出栈顶最前进两个数用运算符a进行计算,并将计算结果入栈
  end loop;

  3,最后将stack的栈元素输入则为运算结果

贴上代码:
首先定义一个简单栈,所有代码中都没有进行异常判断,考虑的是实现过程中,各位看官如果觉得代码垃圾请轻拍:
栈:
/ 自定义栈
class MyStack<T> {
	private Entry<T> top = new Entry<T>(null, null);
	private int size;

	public MyStack() {
		top.next = null;
		top.element = null;
	}

	// 进栈
	public MyStack<T> push(T t) {
		Entry<T> node = new Entry<T>(top.next, t);
		top.next = node;
		size++;
		return this;
	}

	// 出栈
	public T pop() {
		if (size == 0) {
			return null;
		}
		Entry<T> t = top.next;
		Entry<T> foo = top.next.next;
		top.next = foo;
		foo = null;
		size--;
		return t.element;
	}
//得到栈顶元素
	public T top() {
		return top.next.element;
	}

	public int size() {
		return size;
	}
}

// 元素节点
class Entry<T> {
	T element;
	Entry<T> next;

	Entry(Entry<T> next, T e) {
		this.element = e;
		this.next = next;
	}
}


//算法实现类Rpn
//将用户输入的中缀表达式转化成后缀表式
//并根据后缀表达式计算结果表明
public class Rpn {

	//此函数只能处理字符串中的数字全是个位数的情况,如果存在十位以上的则此函数的参数就不能用string了
	//要改为传入一个栈了,并且只计算整数,其它的float,double需稍作修改
	public int countRpn(String src) {
		MyStack<String> stack = new MyStack<String>();
		for (int i = 0; i < src.length(); i++) {
			String foo = src.charAt(i) + "";
			if (!isOperator(foo)) {
				stack.push(foo);
			} else {//如果是运算符
				// 取栈顶两元素进行计算,并将计算结果放入栈顶
				String a = stack.pop();
				String b = stack.pop();
				int temp = count(b, a, foo);// zhu yi chao zuo shu nei xing
				stack.push(temp + "");

			}
		}
		return Integer.parseInt(stack.pop());//最后栈顶元素的值就是表达式的值了
	}

	// 是否为运算符
	public boolean isOperator(String e) {
		if (null == e || "".equals(e)) {
			return false;
		}
		return "+".equals(e) || "*".equals(e) || "-".equals(e) || "/".equals(e);
	}

	// 是否是左括号
	public boolean isLeft(String s) {
		return "(".equals(s);
	}
   //是否是右括号
	public boolean isRight(String s) {
		return ")".equals(s);
	}

	// 根据运算符(e)计算两个数的值班(a,b)
	public int count(String a, String b, String e) {
		int temp1 = Integer.parseInt(a);
		int temp2 = Integer.parseInt(b);
		if ("+".equals(e)) {
			return temp1 + temp2;
		} else if ("-".equals(e)) {
			return temp1 - temp2;
		} else if ("*".equals(e)) {
			return temp1 * temp2;
		} else {
			return temp1 / temp2;
		}
	}

	// 将中缀表达式转化为后缀表达式(逆波兰式)
	public String reverse2Rpn(String src) {
		MyStack<String> stack = new MyStack<String>();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < src.length(); i++) {
			String temp = src.charAt(i) + "";
			if (!isOperator(temp) && !isRight(temp) && !isLeft(temp)) {
				// 操作数,+-直接输出
				sb.append(temp);
			} else if (isOperator(temp)) {
				// 如果是操作符
				if (stack.size() == 0) {// 如果zhan为空则入zhan
					stack.push(temp);
				} else if ("+".equals(temp) || "-".equals(temp)) {
					if (isLeft(stack.top())) {//如果栈顶为左括号,则直接入栈
						stack.push(temp);//直接将操作符入栈
					} else {//从栈顶往下找,直到找到当前栈顶的操作符优先级小于等于当前操作符
						String top = stack.top();
						boolean next = true;
						while (("*".equals(top) || "/".equals(top)) && next) {
							top = stack.pop();
							sb.append(top);// 弹出顶部元素
							next = stack.size() == 0 ? false : true;
						}
					   stack.push(temp);//
					}
					

				} else {// 操作符为:"*"或"/" 直接入栈
					stack.push(temp);// +-的优先级比任何运算符都高,所以直接入栈

				}
			} else if (isLeft(temp)) {//如果是左括号直接入栈
				stack.push(temp);

			} else if (isRight(temp)) {// 如果是右括号,则找到左括号,并将找的过程中的字符全部出栈
				String top = stack.pop();
				boolean next = true;
				while (!isLeft(top) && next) {
					sb.append(top);
					top = stack.pop();
					next = stack.size() == 0 ? false : true;
				}
			}
		}
		while (stack.size() > 0) {
			sb.append(stack.pop());
		}
		return sb.toString();
	}

	public static void main(String[] args) {
		Rpn rpn = new Rpn();
		String src = rpn.reverse2Rpn("((1+2)*2)*4)+9*(1+2)");
		System.out.println("后缀表达式为:"+src);
		System.out.println("计算结果:"+rpn.countRpn(src));
	}

}

  
2
4
分享到:
评论

相关推荐

    java 计算器 源码 逆波兰式

    总之,这个基于逆波兰式的Java计算器项目提供了一个实际的编程练习,有助于提升编程技能,理解数据结构和算法的应用,并加深对计算表达式处理机制的理解。通过分析和运行源码,我们可以更深入地学习和掌握这些概念。

    四则运算求值(中缀转逆波兰式)

    标题 "四则运算求值(中缀转逆波兰式)" 涉及到的是计算机科学中的算法问题,主要集中在表达式求值和转换方法上。逆波兰表示法(Reverse Polish Notation,RPN),也被称为后缀表示法,是一种没有括号的数学表达式...

    android 逆波兰式计算器

    逆波兰式计算器是一种基于后缀表达式的计算工具,它的设计思想是将运算符放在操作数之后,以此简化计算过程,避免了中缀表达式(即我们通常使用的运算符在操作数之间的表达式)中需要考虑优先级和括号的问题。...

    java 中间代码生成 编译原理

    通过对源代码进行三元式、四元式或逆波兰式的转化,可以实现对源代码的分析、优化,并最终生成能在JVM上运行的字节码。 文件“ZhongJianDaiMa”很可能包含了关于Java中间代码生成的具体示例或工具,可以进一步学习...

    编译原理----------算符优先下的逆波兰算法

    通过实际编程实现算法,并观察逆波兰式的结果,可以看到算法是如何将复杂的中缀表达式转换为更易于计算机处理的后缀表达式。这样的实验不仅加深了对逆波兰算法工作原理的理解,还让实践者对编译原理有了更深层次的...

    编译原理实验大全,代码可以直接运行

    在提供的实验文档中,我们可以预期找到关于如何实现这些分析方法的详细步骤,包括编写词法分析器的规则,构建递归下降分析的函数,设计LL(1)分析表,以及逆波兰式的转换和计算算法。这些实验对于理解和掌握编译原理...

    byyli_java.rar_java 语法分析器_syntax analyzer_四元式_生成四元式_语法分析器

    在实际应用中,编译器设计者可能会选择不同的中间表示形式,比如三地址码、逆波兰表示法等,但四元式由于其灵活性和清晰性,常被用于教学和简单的编译器实现中。"bianyi"可能是这个Java语法分析器的源代码或实现文档...

    支持复杂功能计算的计算器

    - **括号匹配**:计算器的核心是正确处理括号内的表达式,这通常通过前缀、后缀或中缀表达式(逆波兰表示法)等方法实现。在中缀表达式中,需要识别并处理括号优先级,确保正确的计算顺序。 - **操作符优先级**:...

    中缀表达式转后辍 编译原理

    其中,中缀表达式和后缀表达式(也称为逆波兰表示法)是编译器设计中处理数学表达式的重要概念。本主题主要探讨如何将中缀表达式转换为后缀表达式,并将这一过程用C#语言实现。 中缀表达式是我们常见的数学表达式...

    带变量算术式解析器(转后置,算值,画树形图)

    这个解析器可以将用户输入的带有变量的算术表达式转化为后置表示法(也称逆波兰表示法),并生成对应的树形结构来直观地展示表达式的运算过程。下面我们将深入探讨这个主题。 1. **后置表示法(逆波兰表示法)**: ...

    简单计算器 中缀转后缀 求和

    在这个场景下,我们关注的是如何实现一个能够处理中缀表达式(即常见的运算符在操作数之间的表达式,如“2 + 3 * 4”)并将其转化为后缀表达式(也称为逆波兰表示法,如“2 3 4 * +”),进而计算求和。这个过程涉及...

    字符串转表达式,进行加减乘除等逻辑运算

    在计算机科学中,字符串转表达式并执行加减乘除等逻辑运算是一项常见的任务,尤其在解析用户输入或处理计算式时。这个过程通常涉及到两个关键步骤:中缀表达式到后缀表达式的转换(也称为逆波兰表示法)以及后缀...

    yuyifenxi.zip_yuyifenxi_翻译成后缀式

    在这个特定的项目“yuyifenxi.zip_yuyifenxi_翻译成后缀式”中,我们关注的是如何将简单的赋值语句转化为后缀表达式(也称为逆波兰表达式),这是一种无括号的数学表示法,可以简化计算过程。 首先,我们要了解什么...

    计算器代码

    这就是所谓的逆波兰表示法(Postfix Notation)或堆栈算法。 此外,异常处理也是计算器代码中不可或缺的部分。考虑如何处理除以零、非法输入等错误情况,确保程序的健壮性。 对于【压缩包子文件的文件名称列表】中...

    OPGComplete.zip_编译器/解释器_Java_

    四元式是另一种表示程序结构的方式,它通常用于中缀表达式的逆波兰表示(后缀表达式)转换。一个四元式包含四个部分:操作数、操作符、结果和附加信息。例如,四元式 "a+b=c" 可以表示为 (a, b, +, c),其中 "+" 是...

    数据结构大作业 表达式翻译

    在这个“数据结构大作业 表达式翻译”中,我们关注的是如何将普通的运算式转化为后缀表达式,也称为逆波兰表示法(Reverse Polish Notation, RPN),然后对这个后缀表达式进行求值。这个过程涉及到栈(Stack)数据...

    计算器app_20162180176梁子宏 1

    2. **逆波兰计算器(Reverse Polish Notation, RPN)**:这是计算器模型设计时采用的算法,它避免了括号的使用,通过运算符堆栈来处理计算过程。RPN算法对于优先级处理和表达式计算非常有效,使得计算过程更简洁。 ...

    money.manager:使用二叉树的简单计算器

    在计算过程中,二叉树通常采用后缀表达式(也称为逆波兰表示法)来表示和解析计算式。后缀表达式将操作符放在操作数之后,避免了括号的使用,简化了运算规则。例如,表达式 "2 + 3 * 4" 在后缀表达式中表示为 "2 3 4...

    编译原理与技术讲义 第9章 语法制导的中间代码翻译.ppt

    后缀式是一种逆波兰表示法,其中运算符位于其操作数之后,如表达式`(a+b)*c`的后缀式为`abc+*`。这种表示法简洁且易于机器处理,但不是所有中间代码都采用后缀式。 在实际应用中,编译器可能会选择几种中间表示的...

    编译原理期末参考资料

    8. **逆波兰表示**(Reverse Polish Notation, RPN)和三元式序列:逆波兰表示是一种无括号的数学表达式表示方式,常用于表达式求值;三元式是编译器将高级语言转化为低级语言的中间形式,便于进行优化和代码生成。 ...

Global site tag (gtag.js) - Google Analytics