3.中缀表达式转后缀表达式

package com.vi.stack;

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

/**
 * 将中缀表达式转成后缀表达式
 * @author vi
 *
 */
public class InfixToSuffixDemo {
    public static void main(String[] args) {
        String expression = "1+((2+3)*4)-5";
        //将表达式存储在List中
        List<String> target = changeToList(expression);
        System.out.println(target);
        //开始转换
        //s1运算符栈
        Stack<String> s1 = new Stack<String>();
        //s2 用list保存结果
        List<String> s2 = new ArrayList<String>();
        for(String item : target ) {
            //如果匹配到数字,存入s2
            if(item.matches("\\d+")) {
                s2.add(item);
            } else{
                    //匹配是非数字,判断是否"(",左括号直接入栈
                    if("(".equals(item)) {
                        s1.push(item);
                    } else if(")".equals(item)) {
                            //是否是")",是的话,需要比较栈顶元素是否(, 不是就弹出栈顶,存入s2中,直到栈顶为"(",然后消掉左括号
                            while(s1.size()>0 && !s1.peek().equals("(")) {
                                s2.add(s1.pop());
                            }
                            s1.pop();
                        } else {
                            //比较运算符与栈顶元素的优先级,低于栈顶元素,将栈顶弹出加入list中,高于栈顶就压入栈
                            while(s1.size()>0 && priority(item) >= priority(s1.peek())) {
                                s2.add(s1.pop());
                            } 
                            s1.push(item);
                        }
                    }
                }
            //将s1栈中剩余的元素依次弹出,存到s2中
            while(s1.size() > 0)
                s2.add(s1.pop());
            //打印s2,得到的就是转后缀表达式的结果
            System.out.println(s2);
        }
    
    
    /**
     * 将目标中缀表达式解析后,存储到list中
     * @param expression
     * @return
     */
    public static List<String> changeToList(String expression) {
        List<String> result = new ArrayList<String>();
        for(int i = 0 ; i < expression.length() ;i++) {
            String cur = expression.charAt(i)+"";
            //判断获得的是否是数字
            if(cur.matches("\\d+")) {//如果是数字,还需要判断下一位是否为数字,是的话进行拼接之后再存储
                int j = i+1;
                //如果下标没有超过表达式长度,并且表达式中的是数字,则进行拼接
                while(j<expression.length() && (expression.charAt(j)+"").matches("\\d+")) {
                    cur = cur + expression.charAt(j)+"";
                    j++;
                }
                result.add(cur);
                i = j - 1;
            } else {
                //如果不是数字,直接存入list中
                result.add(cur);
            }
        }
        return result;
    }
    
    /**
     * 返回目标字符串的优先级
     * @param target
     * @return
     */
    public static int priority(String target) {
        if("+".equals(target) || "-".equals(target)) {
            return 1;
        }
        else if("*".equals(target) || "/".equals(target)) {
            return 2;
        } else {//如果是括号
            return 3;
        }
    }
}

打印结果:

 

步骤总结:

1.准备两个栈,运算符栈s1,存储结果栈s2(可用链表代替)

2.将目标表达式进行扫描

3.如果扫描到数字,存入s2栈中

4.如果扫描到运算符

  4.1 判断是否为"(",是的话直接入s1栈

  4.2 判断是否为")",是的话判断s1栈顶元素是否为"(",不是的话将s1栈顶元素弹出,压入s2栈中,并不断重复过程直到s1栈顶为"(",此时将"("弹出

  4.3 判断当前运算符和栈顶运算符的优先级(括号>* / > + -),如果优先级低于s1栈顶元素,将当前元素压入s1栈,否则将栈顶弹出,压入s2栈,然后将当前元素压入s1栈

5.重复3、4步直至扫描完目标表达式,最后将s1栈中剩余元素弹出,依次压入s2栈中。

6.将s2栈中元素弹出,逆序后的结果就是目标表达式对应的后缀表达式!!!

 

posted on 2019-09-15 09:54  nameless_vi  阅读(187)  评论(0编辑  收藏  举报

导航