逆波兰式生成程序的java实现

内容:掌握语法分析的基本思想,并用高级语言编写逆波兰式生成程序;

要求:利用逆波兰式生成算法编写程序,将从键盘上输入的算术表达式(中缀表达式)转化成逆波兰式。

逆波兰表达式的生成过程涉及到运算符的优先级,下表中列出几个常用运算符的优先关系。

 

常用运算符优先关系矩阵

+

-

*

/

+

-

*

/

 

如上表所示的优先关系矩阵表示了+,-,*,/,↑,(,)等七种运算符之间的相互优先关系。“>、<、=”三种符号分别代表“大于”、“小于”、“相等”三种优先关系。左边的“=”与右边的“(”之间没有优先关系存在,所以表中为空白。

逆波兰表达式生成算法的关键在于比较当前运算符与栈顶运算符的优先关系,若当前运算符的优先级高于栈顶运算符,则当前运算符入栈,若当前运算符的优先级低于栈顶运算符,则栈顶运算符退栈。

下面给出了逆波兰表达式生成算法的流程图。(为了便于比较相邻运算符的优先级,需要设立一个工作栈,用来存放暂时不能处理的运算符,所以又称运算符栈)。

代码

package report;

import java.util.ArrayList;

public class No2 {
	// 存放运算符优先关系矩阵
	private String[][] chars;
	// 存放运算符栈(index=0表示栈底,index=size()-1表示栈顶)
	private ArrayList<String> stack;
	// 存放输入串
	private ArrayList<String> inStr;
	// 存放输出串
	private ArrayList<String> outStr;

	public static void main(String[] args) {

		No2 no2 = new No2();
		String str = "(a+b)*c/d";
		no2.init(str);
		no2.mainFunc();
		for (String currentChar : no2.outStr) {
			System.out.print(currentChar);
		}
	}

	private void mainFunc() {

		// 从左往右扫描中缀表达式
		label1: for (String currentChar : this.inStr) {
			// 输入串为空?
			if (currentChar.equals("#")) {
				// 栈为空?
				while (true) {
					if (this.stack.get(this.stack.size() - 1).equals("#")) {
						break label1;
					} else {
						// 退栈输出
						this.outStr.add(this.stack.get(this.stack.size() - 1));
						this.stack.remove(this.stack.size() - 1);
						continue;
					}
				}
			} else {
				// 运算符?
				if (!this.isChar(currentChar)) {
					// 输出
					this.outStr.add(currentChar);
					continue;
				} else {
					while (true) {
						// 栈是否为空?
						if (this.stack.get(this.stack.size() - 1).equals("#")) {
							// 入栈
							this.stack.add(currentChar);
							continue label1;
						} else {
							// 比较当前运算符与栈顶运算符的优先级
							if (isFirst(currentChar)) {
								// 入栈
								this.stack.add(currentChar);
								continue label1;
							} else {
								// 当前运算符是')'
								if (currentChar.equals(")")) {
									while (true) {
										// 栈顶为'('
										if (this.stack.get(this.stack.size() - 1).equals("(")) {
											// 退栈
											this.stack.remove(this.stack.size() - 1);
											continue label1;
										} else {
											// 栈为空?
											if (this.stack.get(this.stack.size() - 1).equals("#")) {
												System.out.println("ERROR");
											} else {
												// 退栈输出
												this.outStr.add(this.stack.get(this.stack.size() - 1));
												this.stack.remove(this.stack.size() - 1);
												continue;
											}
										}
									}
								} else {
									// 退栈输出
									this.outStr.add(this.stack.get(this.stack.size() - 1));
									this.stack.remove(this.stack.size() - 1);
									continue;
								}
							}
						}
					}
				}
			}
		}
	}

	private void init(String str) {

		System.out.println(str);
		this.stack = new ArrayList<>();
		this.inStr = new ArrayList<>();
		this.outStr = new ArrayList<>();
		// 输入运算符优先关系矩阵8*7
		this.chars = new String[][] { { ">", ">", "<", "<", "<", "<", ">" }, { ">", ">", "<", "<", "<", "<", ">" },
				{ ">", ">", ">", ">", "<", "<", ">" }, { ">", ">", ">", ">", "<", "<", ">" },
				{ ">", ">", ">", ">", ">", "<", ">" }, { "<", "<", "<", "<", "<", "<", "=" },
				{ ">", ">", ">", ">", ">", "", ">" }, { "<", "<", "<", "<", "<", "<", "<" } };

		// 输入输入串
		String[] temps = str.split("");
		for (String temp : temps) {
			this.inStr.add(temp);
		}
		this.inStr.add("#");
		// 输入运算符栈
		this.stack.add("#");
	}

	// 运算符?
	private boolean isChar(String currentChar) {

		return "+-*/↑()".contains(currentChar);
	}

	// 比较当前运算符与栈顶运算符的优先级
	private boolean isFirst(String currentChar) {

		String stackChar = this.stack.get(this.stack.size() - 1);
		int x = "+-*/↑()#".indexOf(stackChar);
		int y = "+-*/↑()#".indexOf(currentChar);
		return this.chars[x][y].equals("<");
	}
}

运行结果

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
逆波兰式(Reverse Polish Notation,RPN),也称后缀表达式(Postfix notation),是一种用于数学表达式的表示方法。逆波兰式将运算符放在操作数的后面,而不是放在前面,这样可以避免使用括号。例如,中缀表达式“1 + 2 * 3”可以写成逆波兰式“1 2 3 * +”。 下面是一个简单的逆波兰式生成程序的示例,使用栈来实现计算: ```python def calculate(op, num1, num2): if op == '+': return num1 + num2 elif op == '-': return num1 - num2 elif op == '*': return num1 * num2 elif op == '/': return num1 / num2 def rpn(expression): stack = [] for char in expression: if char.isdigit(): stack.append(int(char)) elif char in ['+', '-', '*', '/']: num2 = stack.pop() num1 = stack.pop() stack.append(calculate(char, num1, num2)) return stack[0] expression = '12+3*' print(rpn(expression)) # 输出:9 ``` 以上程序使用了一个栈来存储数字,并在遇到运算符时执行相应的计算操作。在本例中,逆波兰式字符串为“12+3*”,它的计算过程如下: 1. 遇到字符 '1',将其压入栈中; 2. 遇到字符 '2',将其压入栈中; 3. 遇到字符 '+',弹出栈顶的两个元素(分别为 2 和 1),计算它们的和,得到 3,将其压入栈中; 4. 遇到字符 '3',将其压入栈中; 5. 遇到字符 '*',弹出栈顶的两个元素(分别为 3 和 3),计算它们的积,得到 9,将其压入栈中; 6. 字符串处理完毕,返回栈顶的元素 9。 通过这种方法,我们可以将中缀表达式转换为逆波兰式,并使用逆波兰式来执行计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值