中缀式转后缀式工具类实现

我们经常用到的表达式叫中缀式,如:1+2,a+b*c;

还有另外一种表达式叫后缀式,叫逆波兰式。

原理我就不赘述了,网上很多介绍。

现在写了个Java中缀式转后缀式的工具类,现分享源码如下:

操作符常量接口:

/**
 * <pre>
 * 操作符常量接口:主要为了保存常量
 * 
 * @author  dobuy
 * 修改时间:  2013-5-22
 * </pre>
 */
public interface Operators
{
    /**
     * 操作符优先级:高
     */
    int HIGH_PRIORITY = 10;
    
    /**
     * 操作符优先级:中
     */
    int MIDIUM_PRIORITY = 5;
    
    /**
     * 操作符优先级:低
     */
    int LOW_PRIORITY = 1;
    
    /**
     * 错误(或未知)的操作符
     */
    int ERROR_PRIORITY = -1;
    
    char OPEN_BRACKET = '(';
    
    char CLOSE_BRACKET = ')';
    
    char ADD = '+';
    
    char SUBRACTION = '-';
    
    char MULTIPLITICATION = '*';
    
    char DIVISION = '/';
    
    char COMPLIMENT = '%';
    
    char SPACE = ' ';
    
    char ZERO = '0';
    
    char NINE = '9';
    
    char LOWER_CASE_A = 'a';
    
    char LOWER_CASE_Z = 'z';
    
    char UPPER_CASE_A = 'A';
    
    char UPPER_CASE_Z = 'Z';
    
    String EMPTY = "";
    
    /**
     * 表达式中待过滤的字符(正则表达式中用到,需转义),下同;
     */
    String OPEN_SQUARE_BRACKET = "\\[";
    
    String CLOSE_SQUARE_BRACKET = "\\]";
    
    String OPEN_CURLY_BRACE = "\\{";
    
    String CLOSE_CURLY_BRACE = "\\}";
}

表达式工具类

import java.util.HashMap;
import java.util.Map;

/**
 * <pre>
 * 操作符处理工具类
 * 
 * @author  dobuy
 * 修改时间:  2013-5-22
 * </pre>
 */
public final class OperatorUtils
{
    /**
     * 保存所有操作符(Key)及优先级(Value)
     */
    private static final Map<Character, Integer> priorities;
    
    private OperatorUtils()
    {
    }
    
    /**
     * 类加载时初始化
     */
    static
    {
        priorities = new HashMap<Character, Integer>();
        
        getPriorities().put(Operators.OPEN_BRACKET, Operators.HIGH_PRIORITY);
        getPriorities().put(Operators.MULTIPLITICATION, Operators.MIDIUM_PRIORITY);
        getPriorities().put(Operators.DIVISION, Operators.MIDIUM_PRIORITY);
        getPriorities().put(Operators.COMPLIMENT, Operators.MIDIUM_PRIORITY);
        getPriorities().put(Operators.ADD, Operators.LOW_PRIORITY);
        getPriorities().put(Operators.SUBRACTION, Operators.LOW_PRIORITY);
    }
    
    /**
     * <pre>
     * 字符是否是操作符(除了字母和数字都是操作符)
     * 
     * @param ch
     * @return
     * @author  dobuy
     * 修改时间:  2013-5-22
     */
    public static boolean isOperator(char ch)
    {
        return !isCharacter(ch) && !isNumber(ch);
    }
    
    /**
     * 
     * <pre>
     * ch1的优先级是否不高于ch2
     * 
     * @param ch1
     * @param ch2
     * @return
     * </pre>
     */
    public static boolean isLowerOfPriority(char ch1, char ch2)
    {
        int priority1 = getPriority(ch1);
        int priority2 = getPriority(ch2);
        
        return priority1 <= priority2;
    }
    
    /**
     * 
     * <pre>
     * 是否字母
     * @param ch
     * @return
     */
    private static boolean isCharacter(char ch)
    {
        return (ch >= Operators.LOWER_CASE_A && ch <= Operators.LOWER_CASE_Z)
            || (ch >= Operators.UPPER_CASE_A && ch <= Operators.UPPER_CASE_Z);
    }
    
    /**
     * 
     * <pre>
     * 字符是否数字
     * 
     * @param ch
     * @return
     */
    private static boolean isNumber(char ch)
    {
        return ch <= Operators.NINE && ch >= Operators.ZERO;
    }
    
    /**
     * 
     * <pre>
     * 获取操作符的优先级
     * 
     * @param ch
     * @return
     */
    private static int getPriority(char ch)
    {
        if (getPriorities().containsKey(ch))
        {
            return getPriorities().get(ch);
        }
        return Operators.ERROR_PRIORITY;
    }
    
    /**
     * 获取 priorities
     * 
     * @return 返回 priorities
     */
    private static Map<Character, Integer> getPriorities()
    {
        return priorities;
    }
}

表达式处理工具类:

import java.util.Stack;

/**
 * <pre>
 * 中缀表达式变后缀表达式工具类
 * 
 * @author  dobuy
 * 修改时间:  2013-5-22
 * </pre>
 */
public final class SuffixExpressionUtils
{
    /**
     * 保存表达式中操作符的栈
     */
    private static final Stack<Character> operators = new Stack<Character>();
    
    /**
     * 表达式的输出结果
     */
    private static final StringBuilder result = new StringBuilder();
    
    private static char lastElement;
    
    /**
     * 私有化构造方法,避免被实例化 <默认构造函数>
     */
    private SuffixExpressionUtils()
    {
    }
    
    /**
     * 
     * <pre>
     * 把中缀式变后缀表达式
     * 
     * @param exp
     * @return
     * </pre>
     */
    public static String getSuffixExp(String exp)
    {
        if (exp == null || exp.length() == 0)
        {
            return exp;
        }
        
        init();
        
        // 所有{}[]全部替换成对应的小括号
        exp = exp.replaceAll(Operators.OPEN_CURLY_BRACE, Operators.OPEN_BRACKET + Operators.EMPTY);
        exp = exp.replaceAll(Operators.CLOSE_CURLY_BRACE, Operators.CLOSE_BRACKET + Operators.EMPTY);
        exp = exp.replaceAll(Operators.OPEN_SQUARE_BRACKET, Operators.OPEN_BRACKET + Operators.EMPTY);
        exp = exp.replaceAll(Operators.CLOSE_SQUARE_BRACKET, Operators.CLOSE_BRACKET + Operators.EMPTY);
        
        // 去掉表达式中所有的" "
        exp = exp.replaceAll(Operators.SPACE + Operators.EMPTY, Operators.EMPTY);
        
        char[] characters = exp.toCharArray();
        
        for (char ch : characters)
        {
            // 如果不是操作符,直接添加
            if (!OperatorUtils.isOperator(ch))
            {
                addCharToResult(ch);
            }
            // 如果是')',则从操作符栈中压出操作符,直到'('为止
            else if (ch == Operators.CLOSE_BRACKET)
            {
                popUntilOpenBracket();
            }
            // 如果是'('或者操作符的优先级高于栈顶元素(如果栈顶时'('时,做特殊处理)
            else if (ch == Operators.OPEN_BRACKET || !isLowerThanTop(ch))
            {
                operators.push(ch);
            }
            // 如果优先级不高于栈顶元素时,栈顶元素出栈,直到栈顶元素优先级高于待入栈元素,并把待入栈元素入栈
            else
            {
                popUntilLowerTop(ch);
            }
            lastElement = ch;
        }
        
        popAllOperators();
        return result.toString().trim();
    }
    
    /**
     * 
     * <pre>
     * 由于定义的是静态方法,执行前,先清空操作符栈中的内容,避免受上一次的干扰
     * 
     * </pre>
     */
    private static void init()
    {
        operators.clear();
        result.delete(0, result.length());
    }
    
    /**
     * 
     * <pre>
     * 碰到')'时,从操作符栈中弹出操作符,直到'('为止
     * 
     * </pre>
     */
    private static void popUntilOpenBracket()
    {
        char lastElement = operators.lastElement();
        
        while (lastElement != Operators.OPEN_BRACKET)
        {
            addCharToResult(operators.pop());
            lastElement = operators.lastElement();
        }
        
        // 最后再弹出'('
        operators.pop();
    }
    
    /**
     * 
     * <pre>
     * 待入栈元素优先级是否不高于栈顶元素,栈为空时,为高于
     * 
     * @param ch
     * @return
     * </pre>
     */
    private static boolean isLowerThanTop(char ch)
    {
        // 操作符栈为空或为'('时,操作符需要直接入栈
        if (operators.isEmpty() || operators.lastElement() == Operators.OPEN_BRACKET)
        {
            return false;
        }
        char topChar = operators.lastElement();
        return OperatorUtils.isLowerOfPriority(ch, topChar);
    }
    
    /**
     * <pre>
     * 当待入栈的操作符优先级不高于栈顶时,栈顶元素出栈,直至栈顶元素低于待入栈元素,然后再把待入栈元素入栈
     * 
     * @param ch
     * </pre>
     */
    private static void popUntilLowerTop(char ch)
    {
        while (isLowerThanTop(ch))
        {
            addCharToResult(operators.pop());
        }
        operators.push(ch);
    }
    
    /**
     * 
     * <pre>
     * 把解析好的字符加入输出结果中
     * 
     * @param ch
     * </pre>
     */
    private static void addCharToResult(char ch)
    {
        // 结果不为空时,同时不连续为非操作符时,加空格后再加字符
        if (OperatorUtils.isOperator(ch) || OperatorUtils.isOperator(lastElement))
        {
            result.append(Operators.SPACE);
        }
        result.append(ch);
    }
    
    /**
     * <pre>
     * 表达式解析完毕,依次从栈顶弹出操作符
     * 
     * </pre>
     */
    private static void popAllOperators()
    {
        while (!operators.isEmpty())
        {
            addCharToResult(operators.pop());
        }
    }
}
单元测试类:

import static org.junit.Assert.assertEquals;

import org.junit.Test;

/**
 * <pre>
 * <一句话功能简述>
 * 
 * </pre>
 */
public class SuffixExpressionUtilsTest
{
    @Test
    public void testGetSuffixExp01()
    {
        assertEquals(SuffixExpressionUtils.getSuffixExp(null), null);
    }
    
    @Test
    public void testGetSuffixExp02()
    {
        String result = SuffixExpressionUtils.getSuffixExp("1+2*3");
        assertEquals(result, "1 2 3 * +");
    }
    
    @Test
    public void testGetSuffixExp02_1()
    {
        String result = SuffixExpressionUtils.getSuffixExp("1*2-3");
        assertEquals(result, "1 2 * 3 -");
    }
    
    @Test
    public void testGetSuffixExp03()
    {
        String result = SuffixExpressionUtils.getSuffixExp("(7-(1+2)/5)*3+8");
        assertEquals(result, "7 1 2 + 5 / - 3 * 8 +");
    }
    
    @Test
    public void testGetSuffixExp04()
    {
        String result = SuffixExpressionUtils.getSuffixExp("(70-(11+22)/55)*63+897");
        assertEquals(result, "70 11 22 + 55 / - 63 * 897 +");
    }
    
    @Test
    public void testGetSuffixExp05()
    {
        String result = SuffixExpressionUtils.getSuffixExp("{[70-(11+22)]/55}*63+897");
        assertEquals(result, "70 11 22 + - 55 / 63 * 897 +");
    }
    
    @Test
    public void testGetSuffixExp06()
    {
        String result = SuffixExpressionUtils.getSuffixExp("{[70-(a+22)]/c}*63+897");
        assertEquals(result, "70 a 22 + - c / 63 * 897 +");
    }
}




你可能感兴趣的:(java,栈,编译原理,后缀式,逆波兰)