1、中缀表达式转后缀
(1)转换过程
- 初始化两个栈,运算符栈s1和存中间结果的栈s2(由于s2不用进行出栈操作,所以为了方便,我们可以用list来代替)
- 从左到右扫描中缀表达式:
- 遇到操作数的时候,直接将其压入s2
- 遇到运算符的时候,则比较其与s1栈顶元素的优先级:
(1)如果s1为空,或栈顶元素为左括号(,则直接将该运算符入栈。
(2)如果优先级比栈顶元素高,也将此运算符压入栈中。
(3)否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(1)进行比较
- 遇到括号的时候
(1)如果是左括号“(”,则直接压入s1。
(2)如果是右括号,则依次弹出栈顶的运算符,并压入s2,直到遇到左括号为止,最后将这一对括号丢掉。
- 将s1中剩余的元素依次压入s2中,s2结果的逆序就是中缀对应的后缀表达式
(2)实现代码如下:
public class PolandExpression2 {
public List<String> expressionToList(String expression){
List<String> expressionList = new ArrayList<>();
for(int i = 0;i < expression.length();i++){
char temp = expression.charAt(i);
if(isOperation(temp)){
expressionList.add(temp + "");
}
else{
String str = "" + temp;
i++;
while(i < expression.length() && !isOperation(expression.charAt(i))){
str = str + expression.charAt(i);
i++;
}
expressionList.add(str);
i--;
}
}
return expressionList;
}
public boolean isOperation(char a){
return a == '+' || a == '-' || a == '*' || a == '/' || a == '(' || a == ')';
}
public List<String> Convert(List<String> expression){
Stack<String> stack = new Stack<>();
List<String> result = new ArrayList<>();
for (String item : expression){
if(!isOperation(item.charAt(0))){
result.add(item);
}
else if(item.equals("(") || stack.isEmpty() || priority(item) > priority(stack.peek())){
stack.push(item);
}
else if(item.equals(")")){
while(!stack.peek().equals("(")){
result.add(stack.pop());
}
stack.pop();
}
else {
while (!stack.isEmpty() && priority(stack.peek()) >= priority(item)){
result.add(stack.pop());
}
stack.push(item);
}
}
while(!stack.isEmpty()){
result.add(stack.pop());
}
return result;
}
public int priority(String item) {
if(item.equals("+") || item.equals("-")){
return 1;
}
else if(item.equals("*") || item.equals("/")){
return 2;
}
return 0;
}
public static void main(String[] args) {
String expression = "1+((2+3)*4)-5";
PolandExpression2 temp = new PolandExpression2();
List<String> expression1 = temp.expressionToList(expression);
System.out.println(temp.Convert(expression1).toString());
}
}
2、利用后缀表达式计算结果
(1)计算步骤
- 从左至右扫描表达式,如果碰见操作数,则直接入栈。
- 遇到操作符,则从栈中弹出两个元素,并将计算结果放入栈中。
- 栈中最后一个元素就是最终的计算结果
(2) 实现代码
class Solution {
public int evalRPN(String[] tokens) {
Stack<String> stack = new Stack<>();
for(int i = 0;i < tokens.length;i++){
if(!tokens[i].equals("+") && !tokens[i].equals("-") && !tokens[i].equals("*") && !tokens[i].equals("/")){
stack.push(tokens[i]);
}
else {
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
if(tokens[i].equals("+")){
stack.push(String.valueOf(num1 + num2));
}
else if(tokens[i].equals("-")){
stack.push(String.valueOf(num1 - num2));
}
else if(tokens[i].equals("*")){
stack.push(String.valueOf(num1 * num2));
}
else if(tokens[i].equals("/")){
stack.push(String.valueOf(num1 / num2));
}
}
}
String result = stack.pop();
return Integer.parseInt(result);
}
}
(3)写的更简洁的代码如下
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList();
for (int i = 0; i < tokens.length; ++i) {
if ("+".equals(tokens[i])) {
stack.push(stack.pop() + stack.pop());
} else if ("-".equals(tokens[i])) {
stack.push(-stack.pop() + stack.pop());
} else if ("*".equals(tokens[i])) {
stack.push(stack.pop() * stack.pop());
} else if ("/".equals(tokens[i])) {
int temp1 = stack.pop();
int temp2 = stack.pop();
stack.push(temp2 / temp1);
} else {
stack.push(Integer.valueOf(tokens[i]));
}
}
return stack.pop();
}
}