android逆波兰表达式的应用(三) 逆波兰表达式的实现 ----- 小达

 逆波兰表达式的实现


       ╮(╯▽╰)╭,刚刚宿舍又熄灯了,今天又犯懒了,本来是想偷懒的,想想还是坚持下吧,又不是什么坏事情,,,摸着瞎瞎来写博客咯~~~,今天就开始结合着代码再将逆波兰表达式的转化问题复习一遍,之前的转化规则再抓过来看看,



1. 正式的开始转化,首先第一个规则就是,遇到数字直接加入到后缀表达式中。(比如第一个数字 9 直接写出)

          2. 第二个规则是碰到运算符,需要做不同的处理。
                           ① 若当前符号堆栈为空,则直接入栈。

                           ② 若是 ‘(’ 就直接将其压入栈中,不管符号堆栈是否为空,也是直接入栈。

                           ③ 若当前符号栈中已经有元素了,则弹出栈顶符号,和遇到的那个符号比较运算优先级(不算括号)。

                                       Ⅰ.弹出的运算符优先级大,则将弹出的运算符写入后缀表达式,再重复步骤③
                                       Ⅱ.弹出的运算符优先级小或者等于,则将弹出的运算符压入栈中,再将遇到的运算符也压入栈中。
                                       Ⅲ.弹出的运算符为‘ ( ’,则先压入 ‘(’,再压入遇到的那个符号
 
                           ④ 若碰到了‘ )’,则不停的从符号栈中弹出运算符至后缀表达式中,直到遇到第一个与之匹配的‘(’为止。这个过                                   程将中缀表达式中的括号直接去除,这也是后缀表达式的优势。

           再转化的过程中是需要一个栈,来存放所遇到的运算符,因此,首先需要弄一个栈类,下面直接上代码,代码中的注释会做详细的解释:
/**
 * Created by dada on 14-11-19.
 * 中缀转换后缀时用到的栈
 * 根据我自己的理解
 * 这个栈就是将数据封装好了之后
 * 只给外部提供固定的操作方式
 * 没接触的时候还以为非常的神秘
 */


public class MyStringStack {
    private int maxNum;         //该栈的大小
    private char[] stackArray;  //主要就是用这个字符数组来存放运算符
    private int top;            //栈顶元素的索引

    public MyStringStack(int max){
        maxNum = max;
        stackArray = new char[maxNum];
        top = -1;
    }
 
    public void push(char c){
        stackArray[++top] = c;
    }

    public char pop(){
        return stackArray[top--];
    }

    public boolean isEmpty(){
        return top == -1;
    }


}

          上面的栈准备好后,下面的就是实现将中缀表达式转化为后缀表达式的代码了:
public class Change {


    private MyStringStack mss;                //用来转换的栈
    private String start;                     //中缀表达式的字符串
    private String result ="";                //中缀表达式变为后缀表达式的结果
    private boolean point_flag = false;       //记录在一个数字中是否出现过小数点,防止多个小数点的出现

    public Change(String start){
        this.start = start;
        mss = new MyStringStack(start.length());
    }

    /**
     * 将中缀表达式中每个字符都取出来
     * 判断不同的字符
     * 并将其进行不同的处理
     */
    
    public String doChange(){                                     //主要的转换函数
        for(int i = 0;i < start.length();i++){
            char c = start.charAt(i);
            switch(c){
            
            /**
             * 这里是将加号和减号看作一种情况
             * 这两个运算符的优先级相同
             * 做出doDeal1的处理
             * 
             * 至于result里面加上一个下划线
             * 是为了在result里面分别前后为两个数字
             * 就像是再上篇博客中用逗号来隔开是一样的道理
             * 
             * point_flag用来标记是否出现了小数点
             */
                case '+':
                case '-':
                    result += '_';
                    point_flag = false;
                    doDeal1(c,1);                                //用来判别并处理是否弹出栈里的运算符
                    break;
                case '*':
                case '/':
                    result += '_';
                    point_flag = false;
                    doDeal1(c,2);                               //用来判别并处理是否弹出栈里的运算符
                    break;
                    
                    /**
                     *根据规则
                     *遇到了左括号就直接push入符号栈 
                     */
                    
                    
                case '(':
                    mss.push(c);
                    point_flag = false;
                    break;
                    
                    /**
                     * 而遇到了右括号
                     * 需要做doDeal2的处理 
                     */
                    
                    
                case ')':
                    doDeal2();                                  //括号的匹配问题
                    point_flag = false;
                    break;
                case '~':
                    result = result + c;
                    break;
                default:
                    if(c == '.'){
                        if(!point_flag){
                            point_flag = true;
                            result = result + c;
                            break;
                        }
                        else{
                            break;
                        }
                    }
                    else{
                        if(point_flag)
                            precision_count++;
                        result = result + c;
                        break;
                    }
            }
        }

        /**
         * 当中缀表达式读取完毕之后
         * 需要再回过头来检查下符号栈
         * 如果为空就没什么工作了
         * 如果里面还有符号,则需要挨个弹出并写入后缀表达式中
         */
        while(!mss.isEmpty())
            result += mss.pop();
        return result;
    }

    /**
     * doDeal1操作
     * 在遇到了加减乘除运算符的时候调用
     * 传进来了一个参数i
     * 用来标明优先级的大小的
     * 加减的优先级大小为1
     * 乘除的优先级大小为2
     * 
     * 该函数做的工作就是检查符号栈是否为空
     * 若为空,该符号直接入栈
     * 否则就弹出栈顶元素
     * 按照我们的规则来就好啦
     */
    public void doDeal1(char c,int i){                      //用来判别并处理是否弹出栈里的运算符
        while(!mss.isEmpty()){
            char topChar = mss.pop();
            if(topChar == '('){
                mss.push(topChar);
                break;
            }
            else{
                int j;
                if(topChar == '+'||topChar == '-')
                    j = 1;
                else
                    j = 2;
                if(j < i){
                    mss.push(topChar);
                    break;
                }

                else
                    result += topChar;
            }
        }
        mss.push(c);
    }

    
    /**
     * doDeal2操作
     * 遇到右括号后
     * 也是按照规则办事~~~~~
     * 你懂的
     */
    public void doDeal2(){                            //括号的匹配问题
        while(!mss.isEmpty()){
            char ch=mss.pop();
            if(ch == '(')
                break;
            else
                result = result + ch;
        }
    }
}

        这样就好啦,两个类就解决了从中缀表达式转化到后缀表达式.今天就写到这里咯,很快就会给大家上怎么计算后缀表达式的代码咯,晚安~~~~~
           

你可能感兴趣的:(逆波兰表达式)