中缀转后缀表达式,带括号的后缀表达式综合计算器,Java栈数据结构实现

简介: 中缀转后缀表达式,带括号的后缀表达式综合计算器,Java栈数据结构实现

文章目录


中缀表达式转后缀表达式思路

逆波兰表达式计算思路

代码实现


中缀表达式转后缀表达式思路


1、初始化两个栈:运算符栈s1和储存中间结果的栈s2


2、从左至右扫描中缀表达式


3、遇到操作数时,将其压入s2


4、遇到运算符时,比较其与s1栈顶运算符的优先级

①如果s1为空,或栈顶运算符为左括号“(”, 则直接将此运算符入栈s1

②否则,若优先级比栈顶运算符的高,也将运算符压入s1

③否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4.1)


5、遇到括号时

①如果是左括号“(”,则直接压入s1

②如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为

止,此时将这一对括号丢弃


6、重复步骤2至5,直到表达式结束


7、将s1中剩余的运算符依次弹出并压入s2


8、依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式


逆波兰表达式计算思路


(3+4)*5-6 对应的后缀表达式为 3 4 + 5 * 6 -,针对后缀表达式求值步骤如下:


1、从左至右扫描,将3和4压入堆栈


2、遇到+运算符,弹出4和3 (4 为栈顶元素,3为次顶元素),计算出3+4的值,得 7,再将7入栈


3、将5入栈


4、接下来是运算符,弹出5和7,计算出75=35,将35入栈


5、将6入栈


6、最后是 - 运算符,弹出35和6,计算35-6=29, 由此得出最终结果


代码实现


import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
 * @Author: Yeman
 * @Date: 2021-10-27-21:59
 * @Description:
 */
public class PolandNotation {
    public static void main(String[] args) {
        //给一个中缀表达式
        String expression = "1+((2+3)*4)-10";
        //将中缀表达式放入List
        List<String> infixList = toInfixExpression(expression);
        //将中缀表达式对应的List转换为逆波兰表达式对应的List
        List<String> suffixList = parseSuffixExpression(infixList);
        //用逆波兰表达式(后缀表达式)进行计算
        int result = calculate(suffixList);
        System.out.println(result);
    }
    //将中缀表达式放入List中
    public static List<String> toInfixExpression(String expression){
        List<String> ls = new ArrayList<>();
        int i = 0; //相当于一个指针,用来遍历表达式
        String str; //用来拼接多位数
        char ch; //每遍历一个,就存入ch
        do {
            //如果不是数,直接加入
            if ((ch = expression.charAt(i)) < 48 || (ch = expression.charAt(i)) > 57){
                ls.add(ch + "");
                i++;
            }else {
                str = "";
                while (i < expression.length() && (ch = expression.charAt(i)) >= 48 && (ch = expression.charAt(i)) <= 57){
                    str += ch;
                    i++;
                }
                ls.add(str);
            }
        }while (i < expression.length());
        return ls;
    }
    //将中缀表达式对应的List转成逆波兰表达式对应的List
    public static List<String> parseSuffixExpression(List<String> infixList){
        Stack<String> s1 = new Stack<String>(); //符号栈
        //由于操作中没有进行过pop,可以使用List<String>替换中间结果栈Stack<String>
        List<String> s2 = new ArrayList<String>();
        for (String item : infixList){
            if (item.matches("\\d+")){
                s2.add(item);
            }else if (item.equals("(")){
                s1.push(item);
            }else if (item.equals(")")){
                while (!s1.peek().equals("(")){
                    s2.add(s1.pop());
                }
                s1.pop(); //将 ( pop出去
            }else {
                while (s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)){
                    s2.add(s1.pop());
                }
                s1.push(item);
            }
        }
        while (s1.size() != 0){
            s2.add(s1.pop());
        }
        return s2;
    }
    //逆波兰表达式计算
    public static int calculate(List<String> expressionList){
        //创建一个栈
        Stack<String> strings = new Stack<String>();
        //遍历列表
        for (String item : expressionList){
            if (item.matches("\\d+")){ //匹配多位数
                strings.push(item);
            }else {
                int num2 = Integer.parseInt(strings.pop());
                int num1 = Integer.parseInt(strings.pop());
                String ch = item;
                int res = 0;
                switch (ch){
                    case "+":
                        res = num1 + num2;
                        break;
                    case "-":
                        res = num1 - num2;
                        break;
                    case "*":
                        res = num1 * num2;
                        break;
                    case "/":
                        res = num1 / num2;
                        break;
                    default:
                        throw new RuntimeException("运算符不正确!");
                }
                strings.push(res + "");
            }
        }
        //for循环结束留在栈里的即为计算结果
        return Integer.parseInt(strings.pop());
    }
}
//该类返回运算符优先级
class Operation{
    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 2;
    private static int DIV = 2;
    public static int getValue(String operation){
        int res = 0;
        switch (operation){
            case "+":
                res = ADD;
                break;
            case "-":
                res = SUB;
                break;
            case "*":
                res = MUL;
                break;
            case "/":
                res = DIV;
                break;
            default:
                System.out.println("运算符不正确!");
                break;
        }
        return res;
    }
}



相关文章
|
20天前
|
存储 缓存 安全
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
37 5
|
1月前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
55 5
|
1月前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
2月前
|
Java API 开发者
Java中的Lambda表达式:简洁代码的利器####
本文探讨了Java中Lambda表达式的概念、用途及其在简化代码和提高开发效率方面的显著作用。通过具体实例,展示了Lambda表达式如何在Java 8及更高版本中替代传统的匿名内部类,使代码更加简洁易读。文章还简要介绍了Lambda表达式的语法和常见用法,帮助开发者更好地理解和应用这一强大的工具。 ####
|
2月前
|
并行计算 Java 编译器
深入理解Java中的Lambda表达式
在Java 8中引入的Lambda表达式,不仅简化了代码编写,还提升了代码可读性。本文将带你探索Lambda表达式背后的逻辑与原理,通过实例展示如何高效利用这一特性优化你的程序。
|
2月前
|
搜索推荐 Java API
探索Java中的Lambda表达式
本文将深入探讨Java 8引入的Lambda表达式,这一特性极大地简化了代码编写,提高了程序的可读性。通过实例分析,我们将了解Lambda表达式的基本概念、使用场景以及如何优雅地重构传统代码。文章不仅适合初学者,也能帮助有经验的开发者加深对Lambda表达式的理解。
|
2月前
|
Java
探索Java中的Lambda表达式
【10月更文挑战第37天】本文将带你深入理解Java的Lambda表达式,从基础语法到高级特性,通过实例讲解其在函数式编程中的应用。我们还将探讨Lambda表达式如何简化代码、提高开发效率,并讨论其在实际项目中的应用。
|
2月前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
52 6
|
2月前
|
Java API
Java中的Lambda表达式与函数式编程####
【10月更文挑战第29天】 本文将深入探讨Java中Lambda表达式的实现及其在函数式编程中的应用。通过对比传统方法,我们将揭示Lambda如何简化代码、提高可读性和维护性。文章还将展示一些实际案例,帮助读者更好地理解和应用Lambda表达式。 ####
|
2月前
|
JSON 自然语言处理 Java
这款轻量级 Java 表达式引擎,真不错!
AviatorScript 是一个高性能、轻量级的脚本语言,基于 JVM(包括 Android 平台)。它支持数字、字符串、正则表达式、布尔值等基本类型,以及所有 Java 运算符。主要特性包括函数式编程、大整数和高精度运算、完整的脚本语法、丰富的内置函数和自定义函数支持。适用于规则判断、公式计算、动态脚本控制等场景。

热门文章

最新文章