算术表达式转四元式

public class Main extends JFrame{
    private JTextArea jTextArea=new JTextArea();
    private JButton jButton=new JButton("选择翻译的文件");
    private JPanel jPanel=new JPanel();

    public static void main(String[] args) {
        new Main();
    }

    public Main(){
        setLayout(new BorderLayout());
        jPanel.add(jButton);
        add(jPanel,BorderLayout.NORTH);
        add(new JScrollPane(jTextArea));

        setSize(500,400);
        setVisible(true);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jButton.addActionListener(new ActionListener() {     //点击按钮,把文件内容翻译为四元式
            @Override
            public void actionPerformed(ActionEvent e) {
                try{
                    String stringFromFile=getStringFromFile();           //从文件获取算术表达式字符串
                    String standerdString=toStanderd(stringFromFile);    //把字符串转化为合适的格式,比如:23*(78-2)变为23 * ( 78 -2 )这样的形式
                    String getString_epilogue = getepilogue(standerdString); //中序算术表达式转为后序,比如a*(b-c)转为bc-a*
                    String getSiYuanShi_string=getSiYuanShi(getString_epilogue);
                    jTextArea.append(getSiYuanShi_string);
                }catch (Exception ex){

                }
            }
        });

    }

    public String getStringFromFile() throws Exception {     //从文件第一行获取算术表达式字符串
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.showOpenDialog(null);
        File file = fileChooser.getSelectedFile();       //选择文件
        Scanner read = new Scanner(file);
        String str = read.next();                       //读取文件第一行

        return str;
    }

    /*这是第一次想到的方法,逻辑上比较绕,感觉不太好理,就写了第二种方法*/
    /*public String toStanderd(String string){           //把字符串转化为合适的格式,比如:23*(78-2)变为23 * ( 78 -2 )这样的形式
        String standerdString="";
        int position=0;
        for(int i=0;i<string.length();i++){
            if(string.charAt(i)=='*'||string.charAt(i)=='-'||string.charAt(i)=='+'||string.charAt(i)=='/'||string.charAt(i)=='('||string.charAt(i)==')'){
                standerdString+=string.substring(position,i)+" "+string.charAt(i)+" ";
                position=i+1;
            }
            if(i==string.length()-1) {     //防止字符串最后一个下标不是运算符而加不进去
                if (string.charAt(string.length() - 1) != '+' && string.charAt(string.length() - 1) != '-' && string.charAt(string.length() - 1) != '*' && string.charAt(string.length() - 1) != '/' && string.charAt(string.length() - 1) != '(' && string.charAt(string.length() - 1) != ')') {
                    standerdString += string.charAt(string.length() - 1);
                }
            }
        }
        //到这里为止,两个相邻操作符会产生两个空格,再一次标准化处理
        String[] str=standerdString.split("  "); //这里是两个空格
        standerdString="";                //将之前的字符串清空
        for(int i=0;i<str.length;i++){
            standerdString+=str[i]+" ";
        }
        System.out.println(standerdString);
        return standerdString;
    }*/

    /*这种方法比上面注释掉的方法更容易理解*/
    /*扫描字符串
    * 扫描到操作数,直接加入另一个符号串
    * 扫描到符号,将" "+符号+" "加入另一个符号串
    * */
    public String toStanderd(String string){           //把字符串转化为合适的格式,比如:23*(78-2)变为23 * ( 78 -2 )这样的形式
        String standerdString="";
        for(int i=0;i<string.length();i++){
            if(string.charAt(i)=='-'||string.charAt(i)=='+'||string.charAt(i)=='/'||string.charAt(i)=='*'||string.charAt(i)=='('||string.charAt(i)==')'){
                standerdString+=" "+string.charAt(i)+" ";
            }else {
                standerdString+=string.charAt(i);
            }
        }

        System.out.println(standerdString);

        //如果表达式里面有两个符号相连,比如:减号后面是括号,则会之间会产生两个空格,下面代码则把两个空格变为一个空格
        String[] str=standerdString.split("  "); //这里是两个空格
        standerdString="";                //将之前的字符串清空
        for(int i=0;i<str.length;i++){
            standerdString+=str[i]+" ";
        }

        System.out.println(standerdString);

        return standerdString;
    }

    /*扫描到操作数,直接压入操作数栈;     - - - -(1)
    * 扫描到符号,压入符号栈,压入符号栈的时候,首先判断扫描到的符号,再考虑符号栈栈顶元素;
    * 如果符号栈栈空,直接压入;          - - - -(2)
    * 如果扫描到的符号是"(",直接压入;    - - - -(3)
    * 如果栈顶元素是"(",直接压入;       - - - -(4)
    * 如果扫描到")",不压入栈,将最接近符号栈栈顶的"("往栈顶方向走的符号全部压出,再压入操作数栈,再把"("压出;  - - - -(5)
    * "*"和"/"的优先级都比"-"和"+"的优先级高;
    * 扫描到的符号比符号栈栈顶的优先级高,则直接压入,否则先将栈顶元素压出,接着压入操作数栈,再将扫描到的符号压入符号栈  - - - -(6)
    * 若中序符号串扫描完成,将符号栈的符号依次压出,压入操作数栈        - - - -(7)
    * */
    public String getepilogue(String string){              //中序算术表达式转为后序,比如a*(b-c)转为bc-a*
        String[] string_array=string.split(" ");    //扫描字符串数组,用两个栈来处理,扫描到操作数压入操作数栈,扫描到符号,压入符号栈
        Stack<String> stack_operand=new Stack<>();         //操作数栈
        Stack<String> stack_symbol=new Stack<>();          //符号栈

        for(int i=0;i<string_array.length;i++){
            if(string_array[i].equals("+")||string_array[i].equals("-")||string_array[i].equals("*")||string_array[i].equals("/")||string_array[i].equals("(")||string_array[i].equals(")")){
                if(stack_symbol.isEmpty()){                        //(2)
                    stack_symbol.push(string_array[i]);
                }
                else if(string_array[i].equals("(")){              //(3)
                    stack_symbol.push(string_array[i]);
                }
                else if(stack_symbol.peek().equals("(")){
                    stack_symbol.push(string_array[i]);            //(4)
                }
                else if(string_array[i].equals(")")){              //(5)
                    while(true){
                        String symbol=stack_symbol.pop();
                        if(symbol.equals("("))
                            break;
                        else
                            stack_operand.push(symbol);
                    }
                }
                /*下面的else if和else为规则(6)*/
                else if((stack_symbol.peek().equals("+")||stack_symbol.peek().equals("-"))&&(string_array[i].equals("*")||string_array[i].equals("/"))){
                    stack_symbol.push(string_array[i]);
                }
                else{
                    stack_operand.push(stack_symbol.pop());
                    stack_symbol.push(string_array[i]);
                }
            }else{
                stack_operand.push(string_array[i]);               //(1)
            }
        }

        /*下面while循环用规则(7)*/
        while(true){
            if(stack_symbol.isEmpty())
                break;
            else
                stack_operand.push(stack_symbol.pop());
        }

        String string_epilogue="";
        for(String str:stack_operand){           //把后序表达式栈转为后序字符串
            string_epilogue+=str+" ";
        }

        System.out.println(string_epilogue);

        return string_epilogue;
    }

    /*扫描后序算术表达式;
    * 扫描到操作数直接压入栈       - - - -(1)
    * 扫描到"+","-","*","/",将栈的栈顶的两个操作数压出,压出的两个操作数和扫描到的符号组合成四元式,再将结果压入栈    - - - -(2)
    * */
    public String getSiYuanShi(String string){
        String SiYuanShiString="";
        String[] string_array=string.split(" ");
        Stack<String> stack=new Stack<>();
        int result_num=0;
        String result="T";
        for(int i=0;i<string_array.length;i++){      //开始扫描字符串数组
            if(string_array[i].equals("+")||string_array[i].equals("-")||string_array[i].equals("*")||string_array[i].equals("/")){
                result_num++;
                result+=result_num;
                SiYuanShiString+="("+string_array[i]+","+stack.pop()+","+stack.pop()+","+result+")\n";
                stack.push(result);
                result="T";
            }else{
                stack.push(string_array[i]);
            }
        }

        return SiYuanShiString;
    }
}

算术表达式

下面是执行结果


第一行是中序转后序需要的格式

第二行是转为后序的算术表达式


具体算法实现,代码里面有详细注释,这里说一下大概过程;

在文件中获取字符串方式就省略了,获取到要翻译的算术表达式字符串之后,转化为一种后面算法所需要的格式,比如5*(52-3)转化为的格式是:5 * ( 52 - 3 ),这一步转化在上面的代码里的方法是toStanderd(String string),转化之后获得的字符串如:第三张图里面第一行字符串,字符串仍然是中序,接下来转化为后序,用到方法getEgilogue(String string),转化为后序之后如:第三张图的第二行字符串。将后序转化为四元式用到的方法getSiYuanShi(String string)。

以上方法具体实现看上面代码,有详细注释。用到了java里面的Stack类以及压栈,出栈和返回栈顶元素的方法。

翻译的算术表达式和翻译结果是图一和图二。

如果看不懂算法注释,可以参考该链接里面的算法http://blog.csdn.net/u012507347/article/details/52245233

  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值