关于Java写逆波兰表达式堆栈操作简单实现

来源:互联网 发布:gephi 布局算法 编辑:程序博客网 时间:2024/06/06 04:29

目的:

      重新熟悉逆波兰表达式算法,通过Java实现逆波兰表达式从容更加深刻理解算法与编程之间的关系;重新熟悉堆栈,并用Java程序实现堆栈的操作。

验证方式:

      图书馆查阅资料,手写计算逆波兰实现基本算法,电脑Java编程实现算法。

过程:

1. 通过读书,重新拾起逆波兰表达式算法的记忆,中缀表达式转化为后缀表达式,从而来实现计算器算法。

2. 中缀表达式转化为后缀表达式其实是运算表达式优先级的体现。

例:中缀表达式:1.a+b*c 2.(a+b)*c 3.(a+b*c)/(d-e)

    后缀表达式:1.abc*+ 2.ab+c*3.abc*+de-/

由上例可以看出,优先级决定后缀表达式的书写。

3. 由具体算法实现逆波兰表达式:可建立两个堆栈,一个用来放置运算符(Sign),一个用来放置依次安排的后缀表达式(RPN)。A.如果进来的是数值,直接压到RPN中。B.如果进来的是‘(’,将它压入Sign。C.如果进来的是运算符:1.查看现在的Sign,如果它是‘(’,直接将运算符压入Sign;2如果不是,则看进来的运算符比Sign现在的顶部元素运算符的优先级是否更高,如果优先级高,将运算符压入Sign,如果不高于,则将Sign现在的顶部元素运算符取出压入到RPN中。C.如果进来的是‘)’,则在Sign中查找‘(’,并从Sign栈顶开始依次取出压入到RPN,直到找到‘(’,并将‘(’删除。

1. Java程序源码:

import java.util.Scanner;

 

public class shuzu_RPN {

   

        private char[]list;//放置最开始输入的,被拆分之后的内容

        private char[]sign;//放置运算符

        private char[]rpnList;//放置逆波兰表达式

        public staticvoidmain(String[] arge){

            shuzu_RPNrpn= newshuzu_RPN();

            //通过键盘输入要要操作的中缀表达式

            rpn.getEquation();

            //将中缀表达式转化为后缀表达式

            rpn.setRPN();

            //输出表达式结果

            rpn.printResult();

        }

   

        //获得整个算数表达式

        public voidgetEquation(){

            System.out.println("请输入算数表达式:");

            //键盘输入

            Scannersc= newScanner(System.in);

            Stringstr= sc.nextLine();

            //获得输入内容后,将字符串内的空格都给消掉

            str.replaceAll(" ","");

            //将输入的字符串转换成字符放在list数组中

            list = newchar[str.length()];

            list = str.toCharArray();

            //输出一遍

            System.out.println("您输入的算数表达式是:");

            for(inti = 0; i<list.length;i++){

                System.out.print(list[i]);

            }

            System.out.println();

        }

   

        //读取list,转化为逆波兰表达式

        public voidsetRPN(){

            //创建一个字符,用来指针作用

            charx;

            //将两个字符数组的长度限定

            sign = newchar[list.length+1];

            rpnList = new char[list.length+1];

            //指符号数组top

            sign[0] = '#';

           

           

            /*在下面的运算中,rpn没加一个,rpnlen将指向下一位

            signlen指向的是当前sign的最高位*/

           

           

            intsignlen = 0;

            //rpn数组top

            intrpnlen = 0;

            for(inti = 0; i < list.length; i++){

                //依次读取字符,进行判断

                x = list[i];

                switch(x){

                    case'(':

                        //符号位加1

                        signlen++;

                        sign[signlen] =x;

                        break;

                    case')':

                        while(sign[signlen]!='('){

                            //依次将括号内容转入到rpnList

                            rpnList[rpnlen] =sign[signlen];

                            //RPN加位

                            rpnlen++;

                            //运算符号位减位

                            signlen--;

                        }

                        //设置为空

                        signlen--;

                        break;

                    //接下来是算数运算符,加减乘除,当后一个优先级不高于前一个优先级,不出

                    case'+':

                    case'-':

                        for(intj = signlen;j >= 0; j--){

                            //+-的运算优先级比*/的低

                            if(sign[j] =='('||signlen == 0){

                                break;

                            }else{

                                //直接将现在的栈顶元素搞到rpnList

                                rpnList[rpnlen] =sign[j];

                                signlen--;

                                rpnlen++;

                            }

                        }

                        signlen++;

                        sign[signlen] =x

                        break;

                    case'*':

                    case'/':

                        for(intj = signlen;j >= 0; j--){

                            //运算优先级,*/的运算优先级高于+-

                            if(sign[j] =='('||sign[j] =='+'||sign[j] =='-'||signlen == 0){

                                break;

                            }else{

                                //把现在的顶部运算符拿出来

                                rpnList[rpnlen] =sign[j];

                                signlen--;

                                rpnlen++;

                            }

                        }

                        signlen++;

                        sign[signlen] =x;             

                        break;

                    //遇到非运算符

                    default:       

                        rpnList[rpnlen] =x;

                        rpnlen++;

                   

                }

            }

            //当符号数组不为空,倒置放到rpn数组

            while(signlen>0){

                rpnList[rpnlen] =sign[signlen];

                signlen--;

                rpnlen++;

            }

        }

        public voidprintResult(){

            System.out.println("生成的逆波兰表达式:");

            for(inti = 0; i < rpnList.length; i++){

                System.out.print(rpnList[i]);

            }

        }

}

 

2. 运算结果:

请输入算数表达式:

((2+1)*(3-1))/(2-1)

您输入的算数表达式是:

((2+1)*(3-1))/(2-1)

生成的逆波兰表达式:

21+31-*21-/_

结果:

  经过查阅资料,仔细验证,终于实现逆波兰表达式,并实现后进先出的堆栈。算法实现并不困难。最大的收获是及时发现自己出现的眼高手低的毛病。及时补漏,并以此为戒,是这次试验最大的收获。




这是很久之前写的一个简单的实现文档,没想到还留着.额...才疏学浅,请多多指教