Inlet类:

package com.hy;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

// 此类用于把算术表达式送入解析器
public class Inlet {
    public static void main(String[] args) throws IOException{
        // 取得用户输入的表达式
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String rawExpression = null;
        System.out.print("请输入算术表达式:");
        rawExpression = br.readLine(); 

        // 得到合法的算术表达式
        String expression="";
        for(int i=0;i<rawExpression.length();i++){
            // 拿到表达式的每个字符
            char c=rawExpression.charAt(i);
            //System.out.print(c+","); 

            if(Character.isDigit(c) || c=='+' || c=='-' || c=='*' || c=='/' || c=='(' || c==')' ){
                //System.out.print(c);
                expression+=c;
            }else{
                System.out.print(" "+c+"不是合法的算术表达式字符.");
                System.exit(0);
            }
        }

        // 送去解析
        Parser p=new Parser(expression);
        //p.print();

        // 转为后序表达式
        Trans t=new Trans(p.getList());
        t.print();
    }
}

Parser类:

package com.hy;

import java.util.ArrayList;
import java.util.List;

// 此类用于将算术表达式解析成包含操作数和操作符的链表
public class Parser {
    private List<String> list;// 用于存储表达式的链表

    public List<String> getList() {
        return list;
    }

    public Parser(String expression){
        list=new ArrayList<String>();

        String str="";
        for(int i=0;i<expression.length();i++){
            char c=expression.charAt(i);

            if(Character.isDigit(c)){
                str+=c;
            }else{
                if(str.length()>0){// 此判断是因为有+(这种符号相连的情况
                    //System.out.println(str);
                    list.add(str);
                    str="";
                }

                //System.out.println(c);
                list.add(String.valueOf(c));
            }
        }

        if(str.length()>0){// 此判断是因为可能表达式不是以=结尾
            //System.out.println(str);
            list.add(str);
            str="";
        }
    }

    public void print(){
        for(String str:list){
            System.out.println(str);
        }
    }
}

Trans类:

package com.hy;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

// 此类用于将中序表达式转译成后序表达式
public class Trans {
    private Stack<String> stack;// 用于存储操作符的栈
    private List<String> postfixList;// 用于存储后序表达式的链表

    public Trans(List<String> list){
        stack=new Stack<String>();
        postfixList=new ArrayList<String>();

        for(String str:list){
            // 这个分支是当前项是操作符号的情况
            if(str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/") || str.equals("(") || str.equals(")")  ){
                String opThis=str;

                if(stack.size()==0){
                    // 如果栈为空,直接把操作符推入栈
                    stack.push(opThis);
                }else if(str.equals("(")){
                    // 如果操作符是左括号,直接推入栈
                    stack.push(opThis);
                }else if(str.equals(")")){
                    // 如果操作符是右括号,则往前找左括号,将左括号之后的操作符放到后续表达式列表中

                    while(stack.peek().equals("(")==false){ // stack.peek()是取栈顶元素而不弹出
                        postfixList.add(stack.pop());
                    }

                    stack.pop();// 左括号丢弃,由此完成了去括号的过程
                }else{
                    // 看栈顶元素,如果它优先级大于等于当前操作符的优先级,则弹出放到后续表达式列表中
                    while( stack.size()>0 && (getOpLevel(stack.peek())>=getOpLevel(opThis)) ){
                        postfixList.add(stack.pop());
                    }

                    stack.push(opThis);// 当前操作符入栈
                }

            }else{
                // 这个分支是当前项是操作数的情况
                postfixList.add(str);// 操作数直接入栈
            }
        }

        // 将栈中余下的操作符弹出放到后续表达式列表中
        while(stack.size()>0){
            String opTop=stack.pop();
            postfixList.add(opTop);
        }
    }

    // 取得操作符的等级
    private int getOpLevel(String op){
        if(op.equals("+") || op.equals("-") ){
            return 0;
        }else if(op.equals("*") || op.equals("/") ){
            return 1;
        }

        return -1;
    }

    public void print(){
        for(String str:postfixList){
            System.out.print(str);
        }
    }
}

执行结果:

请输入算术表达式:1+2-3
12+3-

请输入算术表达式:1+2*3
123*+

请输入算术表达式:2*(3+4)
234+*

请输入算术表达式:1+2*(6-4)
1264-*+

请输入算术表达式:1+2*(5-4)+6-7
1254-*+6+7-

请输入算术表达式:(1+2)*3-4*(6-5)
12+3*465-*-

喝水不忘挖井人,参考资料如下:

1.Java数据结构与算法(第二版) [美]Robert Lafore著

2.栈的应用--中序表达式转后序表达式  https://www.cnblogs.com/bgmind/p/3989808.html

--END--2019年9月2日12点20分

[Java]将算术表达式(中序表达式Infix)转成后续表达式Postfix的更多相关文章

  1. 二叉树 Java 实现 前序遍历 中序遍历 后序遍历 层级遍历 获取叶节点 宽度 ,高度,队列实现二叉树遍历 求二叉树的最大距离

    数据结构中一直对二叉树不是很了解,今天趁着这个时间整理一下 许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显 ...

  2. PAT-1099(Build A Binary Search Tree)Java实现+二叉排序树的中序遍历和层次遍历

    Build A Binary Search Tree PAT-1099 本题有意思的一个点就是:题目已经给出了一颗排序二叉树的结构,需要根据这个结构和中序遍历序列重构一棵二叉排序树. 解法:可以根据中 ...

  3. PAT-1086(Tree Traversals Again)Java语言实现+根据中序和前序遍历构建树并且给出后序遍历序列

    Tree Traversals Again Tree Traversals Again 这里的第一个tip就是注意到非递归中序遍历的过程中,进栈的顺序恰好是前序遍历的顺序,而出栈的顺序恰好是中序遍历的 ...

  4. C语言实现链式二叉树静态创建,(先序遍历),(中序遍历),(后续遍历)

    #include <stdio.h>#include <stdlib.h> struct BTNode{ char data ; struct BTNode * pLchild ...

  5. IDEA问题java: -source 1.6 中不支持diamond、 lambda 表达式

    文章目录 一.问题:连片的java: -source 1.6 中不支持 diamond 运算符.lambda 表达式 二.解决方法: 1.在微信群里问大佬,大佬在玩游戏,回复的比较慢 2.自己查Goo ...

  6. [Java]算术表达式组建二叉树,再由二叉树得到算式的后序和中序表达式

    Entry类: package com.hy; import java.io.BufferedReader; import java.io.IOException; import java.io.In ...

  7. [Java]算术表达式求值之三(中序表达式转二叉树方案 支持小数)

    Entry类 这个类对表达式的合法性进行了粗筛: package com.hy; import java.io.BufferedReader; import java.io.IOException; ...

  8. [Java]算术表达式求值之二(中序表达式转后序表达式方案,支持小数)

    Inlet类,入口类,这个类的主要用途是验证用户输入的算术表达式: package com.hy; import java.io.BufferedReader; import java.io.IOEx ...

  9. [Java]算术表达式求值之一(中序表达式转后序表达式方案)

    第二版请见:https://www.cnblogs.com/xiandedanteng/p/11451359.html 入口类,这个类的主要用途是粗筛用户输入的算术表达式: package com.h ...

随机推荐

  1. easyui datagrid连续删除问题

    如果在datagrid中直接将index传给easyui自带的deletRow方法来删除当前点击行,一开始并没有问题,但是当连续删除的时候就或出问题了. 原因是datagrid行是根据datagrid ...

  2. Nginx(web服务器)与Tomcat(应用服务器)搭建集群

    Nginx作为互联网最常用的web服务器,高性能的HTTP和反向代理使它经常作为Tomcat集群的方案.Nginx官方只支持使用HTTP协议的集成,但是如果你想使用AJP协议集成,可以使用阿里开源的n ...

  3. 基于linux与busybox的reboot命令流程分析

    http://www.xuebuyuan.com/736763.html 基于Linux与Busybox的Reboot命令流程分析 ********************************** ...

  4. Linux工具之netstat

        1.简介   Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicas ...

  5. 记录一个url_for的用法

    使用url_for生成url时,需要将url协议从http换成https时,就可以通过在函数中增加参数实现: url_for('secure_thingy', _external=True, _sch ...

  6. adb简介

    Android 调试桥 (adb) 是一种功能多样的命令行工具,可让您与设备进行通信.adb 命令便于执行各种设备操作(例如安装和调试应用),并提供对 Unix shell(可用来在设备上运行各种命令 ...

  7. 清北学堂dp图论营游记day4

    依然zhx讲. 讲了概率与期望: 期望:事件结果的平均大小.记作E(x). E(x)=每种结果的大小与其概率的乘积的和. 例如,记掷一枚骰子的点数为x E(x)=1*(1/6)+2*(1/6)+3*( ...

  8. [转帖]微軟将从 .NET 4 以后的版本弃用 System.Data.OracleClient

    转帖--微軟将从 .NET 4 以后的版本弃用 System.Data.OracleClient Posted on -- : eaglet 阅读() 评论() 编辑 收藏 原贴 http://www ...

  9. pidstat 命令详解(转载)

    转自https://www.jianshu.com/p/3991c0dba094 pidstat 概述 pidstat是sysstat工具的一个命令,用于监控全部或指定进程的cpu.内存.线程.设备I ...

  10. Newsgroups数据集研究

    1.数据集介绍 20newsgroups数据集是用于文本分类.文本挖据和信息检索研究的国际标准数据集之一. 数据集收集了大约20,000左右的新闻组文档,均匀分为20个不同主题的新闻组集合. 一些新闻 ...