您的位置:首页 > 编程语言 > Java开发

Java 学习笔记---逆波兰表达式

2017-08-09 14:52 579 查看
以下是个人根据逆波兰式的算法写的java程序,如有错误或者意见,欢迎留言或者其他方式。

import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.Test;

public class Generator {

/**
* 定义运算符优先级
*
* @param operator
* @return int 优先级的数字
*/
public static int getPriority(String operator) {
final int plusPriority = 2;
final int multiplyPriority = 3;

if ("+".equals(operator))
return plusPriority;

if ("-".equals(operator))
return plusPriority;

if ("*".equals(operator))
return multiplyPriority;

if ("/".equals(operator))
return multiplyPriority;

if ("%".equals(operator))
return multiplyPriority;

return 0;
}

/**
* 中序表达转逆序表达
*
* @param str
*/
public Stack<String> cal(String str) {

Stack<String> s1 = new Stack<String>();// 逆波兰式
Stack<String>
e9ca
s2 = new Stack<String>();// 临时空栈

// 分割字符,运算数,运算符
String[] ch1 = split(str);

// 表达式转换
for (int i = 0; i < ch1.length; i++) {

String c = ch1[i];
// (1)如果遇到的是数字,我们直接加入到栈S1中;
if (isNumber(c)) {
s1.push(c);
continue;
}

// (2)如果遇到的是左括号,则直接将该左括号加入到栈S2中;
if (c.equals("(")) {
s2.push(c);
continue;
}

if (c.equals(")") && s2.isEmpty()) {
new Exception();
}

// (3)如果遇到的是右括号,那么将栈S2中的运算符一次出栈加入到栈S1中,直到遇到左括号,但是该左括号出栈S2并不加入到栈S1中
if (c.equals(")")) {
String temp = (String) s2.pop();

while (!temp.equals("(")) {
if (temp.isEmpty())
new Exception();
s1.push(temp);
temp = (String) s2.pop();
}
continue;
}

// (4)如果遇到的是运算符,包括单目运算符和双目运算符 :
// 4.1 如果栈s2为空,则直接将运算符加入栈s2
if (s2.isEmpty()) {
s2.push(c);
continue;
}

/**
* (2)如果此时栈S2不为空,当前遍历的运算符的优先级大于等于栈顶运算符的优先级,那么直接入栈S2;
*/
if (!isHight((String) s2.peek(), c)) {

s2.push(c);
continue;
} else {
// (3)如果此时栈S2不为空,当前遍历的运算符的优先级小于栈顶运算符的优先级,则将栈顶运算符一直出栈加入到栈S1中,
// 直到栈为空或者遇到一个运算符的优先级小于等于当前遍历的运算符的优先级,此时将该运算符加入到栈S2中;
String temp = (String) s2.pop();
while (true) {
s1.push(temp);
if (s2.isEmpty()) {
s2.push(c);
break;
}
if (!isHight(temp, c)) {
s2.push(c);
break;
}
temp = (String) s2.pop();
}
continue;
}

}

// (5)栈S2中仍然存在运算符,那么将这些运算符依次出栈加入到栈S1中,直到栈为空。
while (!s2.isEmpty()) {
s1.push(s2.pop());
}
return s1;
}

// 分割字符串
private String[] split(String src) {
StringBuilder sb = new StringBuilder(src.length());
for (char ch : src.toCharArray()) {
if (isOperator(String.valueOf(ch))) {
sb.append("," + ch + ",");
} else {
sb.append(ch);
}
}
String string = sb.toString().replaceAll(",+", ",");
return string.split(",");
}

/**
* 判断字符是否是数字
*
* @param str
* @return boolean
*/
public boolean isNumber(String str) {
Pattern pattern = Pattern.compile("^[0-9a-zA-Z]*$");
Matcher matcher = pattern.matcher(str);
return matcher.matches();
}

/**
* 判断字符是否是运算符
*
* @param str
* @return boolean
*/
public boolean isOperator(String str) {
Pattern pattern = Pattern.compile("^[\\+\\-\\*\\/\\%\\(\\)\\{\\}\\[\\]]");
Matcher matcher = pattern.matcher(str);
return matcher.matches();
}

/**
* 比较字符串优先级
*
* @param str
* @param str2
* @return
*/
private boolean isHight(String str, String str2) {
return getPriority(str) > getPriority(str2);
}

public double getRes(String str) {
Stack<String> s = cal(str);
Stack<Double> res = new Stack<Double>();
for (String string : s) {
if (isNumber(string)) {
res.push(Double.valueOf(string.toString()));
} else {
Double x = res.pop();
Double y = res.pop();
switch (string) {
case "+":
res.push(x + y);
break;
case "-":
res.push(y - x);
break;
case "*":
res.push(y * x);
break;
case "/":
if (x != 0)
res.push(y - x);
else {
new Exception();
}
break;
case "%":
if (x != 0)
res.push(y % x);
else {
new Exception();
}

}
}
}
Double result = res.pop();
res.clear();
return result;
}

@Test
public void test() {
System.err.println("569+365*(24+60)-1993%9+11/8=" + getRes("569+365*(24+60)-1993%9+11/8"));

}
}


运算的结果:

569+365*(24+60)-1993%9+11/8=31228.0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: