24-咸鱼学Java-栈的应用-波兰式转逆波兰式

波兰式介绍

波兰式是在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之前,所以,这种表示法也称为前缀表达式。

逆波兰式介绍

逆波兰式(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)


其不同的地方只是运算符的位置不同
举个例子2+3为波兰式,23+就为逆波兰式
其转换方法为
这里写图片描述
这种操作类似于

原式操作结果操作后原式
2+3*5-4*(5-3)2为数字,直接放入结果2+3*5-4*(5-3)
+3*5-4*(5-3)+为操作符且栈为空 +入栈+23*5-4*(5-3)
3*5-4*(5-3)3为数字,直接放入结果+23*5-4*(5-3)
*5-4*(5-3)*和栈内+进行比较 *优先级大 *入栈+*25-4*(5-3)
5-4*(5-3)5为数字,直接放入结果+*235-4*(5-3)
-4*(5-3)-和栈内*比较 *优先级大*出栈+235*-4*(5-3)
-4*(5-3)-和栈内+比较 +优先级大 +出栈235*+-4*(5-3)
-4*(5-3)-为操作符且栈为空 -入栈-235*+4*(5-3)
4*(5-3)4为数字,直接放入结果-235*+4*(5-3)
*(5-3)*和栈内-比较 *优先级大 *入栈-*235*+4(5-3)
(5-3)(和栈内*比较 (优先级大 (入栈-*(235*+45-3)
5-3)5为数字,直接放入结果-*(235*+45-3)
-3)-和栈内(比较 -优先级大 -入栈-*(-235*+453)
3)3为数字,直接放入结果-*(-235*+453)
))和栈内-比较 -优先级大 -出栈-*(235*+453-)
))和栈内)比较 ()优先级相等 (出栈-*235*+453-
原式处理完毕栈不为空,逐个弹出235*+453-*-

结果235*+453-*-

代码实现

stack

package time20180506;
/**
 * 栈
 * @author 焦焱
 * 
 */
public class Stack {
    /**
     * 栈顶标记
     */
    int top;
    /**
     * 栈内元素
     */
    char[] elem;
    /**
     * 无参构造
     */
    public Stack()
    {
        this(10);
    }
    /**
     * 有参构造
     * @param size
     */
    public Stack(int size) {
        this.top = 0;
        this.elem = new char[size];
    }

    /**
     * 入栈
     * @param val
     * @return
     */
    public boolean push(char val)
    {   //先判断是否满
        if(isFull()){
            return false;
        }
        //如果不为空,赋值,并且栈顶往上走一位
        this.elem[this.top++] = val;
        return true;
    }
    /**
     * 出栈
     * @return
     */
    public char pop() {
        //先判断是否为空
        if(isEmpty()){
            System.out.println("当前栈为空");
            return '/' ;
        }
        //返回当前栈顶减一位置的的元素,并且栈顶往下减一。
        return elem[--top];
    }
    /**
     * 获得栈顶元素
     * @return
     */
    public char getTop()
    {   //如果为空返回-1,如果
        return isEmpty()?'/':elem[this.top-1];
    }
    /**
     * 判断是否满
     * @return
     */
    public boolean isFull()
    {
        return top==this.elem.length;
    }
    /**
     * 判断是否空
     * @return
     */
    public boolean isEmpty()
    {
        return top==0;
    }
    /**
     * 显示当前栈内所有元素
     */
    public void show()
    {
        System.out.println("\t栈顶------->栈底");
        System.out.print("当前栈数据为:");
        for (int i = top-1; i >=0; i--) {
            System.out.print(elem[i]+" ");
        }
        System.out.println();
    }
}

bolan

package time20180506;

/**
 * 逆波兰式
 * @author 焦焱
 *
 */
public class Bolan {
    //优先级越高值越小
    /**
     * 栈内加法
     */
    public static final int OPERATORS_PRIO_PLUS_IN = 4;  
    /**
     * 栈内减法
     */
    public static final int OPERATORS_PRIO_SUB_IN  =  4;   
    /**
     * 栈内乘法
     */
    public static final int  OPERATORS_PRIO_MULTY_IN  =  2; 
    /**
     * 栈内除法
     */
    public static final int OPERATORS_PRIO_DIV_IN  =  2 ;  
    /**
     * 栈内左括号
     */
    public static final int OPERATORS_PRIO_LEFT_BRAK_IN  =  10;  

    /**
     * 栈外加法
     */
    public static final int OPERATORS_PRIO_PLUS_OUT  =  5 ; 
    /**
     * 栈外减法
     */
    public static final int OPERATORS_PRIO_SUB_OUT  =   5;   
    /**
     * 栈外乘法
     */
    public static final int OPERATORS_PRIO_MULTY_OUT  =  3; 
    /**
     * 栈外除法
     */
    public static final int OPERATORS_PRIO_DIV_OUT  =  3;   
    /**
     * 栈外左括号
     */
    public static final int OPERATORS_PRIO_LEFT_BRAK_OUT =  1;  
    /**
     * 栈外右括号
     */
    public static final int OPERATORS_PRIO_RIGHT_BRAK_OUT =  10;  
    /**
     * 错误
     */
    public static final int OPERATORS_PRIO_ERROR = -1;

    /**
     * 获得其优先级
     * @param opera 运算符
     * @param instack 是否在栈内
     * @return 其优先级,优先级越大值越小
     */
    public static int getPrio(char opera,boolean instack)
    {
        int prio = OPERATORS_PRIO_ERROR;
        if(instack)
        {
            switch(opera)
            {
            case '+':
                prio = OPERATORS_PRIO_PLUS_IN;
                break;
            case '-':
                prio = OPERATORS_PRIO_SUB_IN;
                break;
            case '*':
                prio = OPERATORS_PRIO_MULTY_IN;
                break;
            case '/':
                prio = OPERATORS_PRIO_DIV_IN;
                break;
            case '(':
                prio = OPERATORS_PRIO_LEFT_BRAK_IN;
                break;
            default:
                prio = OPERATORS_PRIO_ERROR;
                break;
            }
        }
        else
        {
            switch(opera)
            {
            case '+':
                prio = OPERATORS_PRIO_PLUS_OUT;
                break;
            case '-':
                prio = OPERATORS_PRIO_SUB_OUT;
                break;
            case '*':
                prio = OPERATORS_PRIO_MULTY_OUT;
                break;
            case '/':
                prio = OPERATORS_PRIO_DIV_OUT;
                break;
            case '(':
                prio = OPERATORS_PRIO_LEFT_BRAK_OUT;
                break;
            case ')':
                prio = OPERATORS_PRIO_RIGHT_BRAK_OUT;
                break;
            default:
                prio = OPERATORS_PRIO_ERROR;
                break;
            }
        }
        return prio;
    }
    /**
     * 转换
     * @param strMid
     * @param strLast
     * @return 
     */
    public static String strMidToLast(String strMid)
    {   //栈
        Stack stack = new Stack();
        //逆波兰式结果
        StringBuffer string = new StringBuffer();
        //栈内优先级
        int prioIn;
        //栈外优先级
        int prioOut;
        //循环遍历strMid
        for(int i=0;i<strMid.length();i++)
        {   //检查是不是数字,如果为数字,直接放到结果里面
            if(Character.isDigit(strMid.charAt(i)))
            {
                string.append(strMid.charAt(i));
            }
            else
            {   //如果不为数字而且栈为空
                if(stack.isEmpty()) 
                {
                    //将运算符入栈
                    stack.push(strMid.charAt(i));
                }
                //如果栈不为空
                else
                {   //获取栈内的运算符的优先级
                    prioIn = getPrio(stack.getTop(),true);
                    //获取栈外的运算符的优先级
                    prioOut = getPrio(strMid.charAt(i),false);
                    //如果栈外优先级比栈内的大
                    if(prioIn < prioOut)
                    {   
                        //把栈内的运算符弹出,放入结果
                        string.append(stack.pop());
                        //因为第i个数据还得和栈的下一个运算符比较
                        //所以需要手动将其置回
                        i--;
                    }
                    //当两个相等的时候就是栈内左括号和栈外有括号
                    //只需要将栈内左括号弹出即可
                    else if(prioIn == prioOut)
                    {
                        stack.pop();
                    }
                    //当栈外优先级比栈内的小则将其放入栈中
                    else
                    {
                        stack.push(strMid.charAt(i));
                    }
                }
            }
        }
        //如果栈不为空,则其内还有运算符,需要逐个弹出,放到结果后面
        while(!stack.isEmpty())
        {
            string.append(stack.pop());
        }
        return string.toString();
    }
    public static void main(String[] args) {
        String a = "2+3*5-4*(5-3)";
        String strMidToLast = strMidToLast(a);
        System.out.println(strMidToLast);
    }


}

测试结果235*+453-*-

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值