IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Java数据结构Day11--栈实现逆波兰表达式(后缀表达式)计算器 -> 正文阅读

[数据结构与算法]Java数据结构Day11--栈实现逆波兰表达式(后缀表达式)计算器

今天和几个同学正好谈到,就分享一下
SimpleDateFormat具有线程安全问题,在Java8之后,可以使用线程安全的LocalDate、LocalTime、或者LocalDateTime,但是说实话,这个LocalDate比SimpleDateFormat麻烦太多了..但是能写一个工具类来封装一下常用的方法.所以好像也不是那么难搞

?

不吹牛了不吹牛了,说正事

目录

前缀表达式

中缀表达式

后缀表达式

中缀转后缀思路:

代码一:(后缀表达式计算器)

代码二:(中缀表达式计算器)?

前缀表达式

"(3+4)*5-6"如果用前缀表达式来表示,就是"?- * + 3 4 5 6?"
计算前缀表达式:从右到左扫描前缀表达式,遇到数字就push进栈,遇到符号就从栈中pop出栈顶和次顶的元素与该符号做计算(栈顶元素为num1,次顶元素为num2),再把结果值push入栈;如此循环,直到只剩下一个数,即是结果

中缀表达式

"(3+4)*5-6"这种类型就是中缀表达式,虽然我们可以清楚的从中分析出计算逻辑,但是对于计算机来说,还需要判断优先级,所以在计算机计算时,会将中缀表达式转换成其他类型的表达式

后缀表达式

"(3+4)*5-6"如果用后缀表达式来表示,就是" 3 4 + 5 * 6 - "
计算后缀表达式:从左到右扫描后缀表达式,遇到数字就push进栈,遇到符号就从栈中pop出栈顶和次顶的元素与该符号做计算(栈顶元素为num2,次顶元素为num1),再把结果值push入栈;如此循环,直到只剩下一个数,即是结果?

你这个num1和num2是啥东西?换个名字有啥区别呢? -->? "num1 操作符 num2" 这应该能懂了吧,其实就是前缀表达式是把栈顶元素放在前面(作为被减数,被除数这种),后缀表达式把栈顶元素放在后面


有小朋友又要问了:那么,怎么把我们写的中缀表达式转换为后缀表达式呢?
这玩意比较麻烦,涉及到的步骤很多

中缀转后缀思路:

1.初始化两个栈:运算符栈s1与储存中间结果的栈s2
2.从左到右扫描中缀表达式
3.遇到数字时,push进s2
4.遇到运算符X时,先与s1栈顶操作符比较优先级
? ?①如果s1为空或者栈顶为''("左括号或者X优先级大于栈顶符号优先级
? ? ? ?push入s1
? ?②若不满足以上,pop出s1栈顶的操作符,并将其push进s2;? ? ? ? ? 然后回到第4步开头,继续与s1新栈顶元素比较? ? ? ?
5.遇到括号时
? ?①如果是"("左括号,直接push进s1
? ?②如果是")"右括号,则一次pop出s1栈顶的运算符,并push进s2,直到遇到"("左括号为止,然后将这一对括号丢弃
6.遍历结束之后,将s1中的操作符依次pop并push进s2
7.pop出全部的s2元素,结果的倒序即为所求的后缀表达式

代码一:(后缀表达式计算器,数组实现的栈)

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

public class PolandNotation {
    public static void main(String[] args) {
        System.out.println("请输入一个后缀表达式");
        Scanner scanner = new Scanner(System.in);
        String question = scanner.next();
        List<String> listString = getListString(question);
        System.out.println(findResult(listString));
    }

    //编写一个把字符串变为一个个单独的字符串格式
    public static List<String> getListString(String value) {
        ArrayList<String> arr = new ArrayList<>();
        for (int i = 0; i < value.length(); i++) {
            String single = value.substring(i, i + 1);
            arr.add(single);
        }
        return arr;
    }

    //判断是否是操作符
    public static boolean isOper(String val){
        return val.equals("*") || val.equals("/") || val.equals("+") || val.equals("-");
    }
    //对传入的字符串列表进行计算
    public static int findResult(List<String> list){
        int num1,num2,tmp;
        ArrayStack arrayStack = new ArrayStack(list.size());
        for (String s : list) {
            if (isOper(s)){
                //是操作符,弹出数字计算
                num2 = arrayStack.pop();
                num1 = arrayStack.pop();
                tmp = calculate(num1, num2, s);
                arrayStack.push(tmp);
            }else{
                //是数字,入栈
                arrayStack.push(Integer.parseInt(s));
            }
        }
        return arrayStack.pop();
    }

    //计算逻辑
    public static int calculate(int num1,int num2, String s){
        switch(s) {
            case "+":
                return num1 + num2;
            case "-":
                return num1 - num2;
            case "*":
                return num1 * num2;
            case "/":
                return num1 / num2;
        }
        //s只可能是以上四种,这里return 0 是为了不报错
        return 0;
    }
}
class ArrayStack{
    int maxSize;
    int[] array;
    //栈顶指针默认指向-1,当有数据push后,top++,指向0号位
    int top = -1;
    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        array = new int[maxSize];
    }
    public void push(int num){
        if (top == maxSize - 1){
            System.out.println("栈满,无法添加");
            return;
        }
        array[++top] = num;
    }
    public int pop(){
        if (top == -1){
            System.out.println("栈空,无法出栈");
            return -9999999;
        }
        return array[top--];
    }
    public void popall(){
        if (top == -1){
            System.out.println("栈空,无法出栈");
            return;
        }
        int i = 1;
        while (top != -1){
            System.out.println("第" + i++ + "个为" + array[top--]);
        }
    }
    public void showall(){
        if (top == -1){
            System.out.println("栈空,无法出栈");
            return;
        }
        for (int i = 0; i <= top; i++) {
            System.out.println("第" + i + "个为" +array[i]);
        }
    }
}

代码二:(中缀表达式转换后缀表达式计算器)?

靠!写了一个多小时....这玩意儿果然不是我应该做的....

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

public class PolandNotation {
    public static void main(String[] args) {
        System.out.println("请输入一个表达式");
        Scanner scanner = new Scanner(System.in);
        String question = scanner.next();
        //字符串转换为一个个的数字和操作符和括号
        List<String> midList = toMidList(question);
        //转换为后缀表达式
        List<String> suffixList = toSuffixList(midList);
        //计算后缀表达式
        int result = figure(suffixList);
        System.out.println(result);
        //例:输入(3+4)*5-6 得到29!
    }

    //用该方法将输入的中缀字符串做一个划分,顺序划分成数字和操作符
    public static List<String> toMidList(String question) {
        ArrayList<String> arr = new ArrayList<>();
        char c;//扫描变量
        int i = 0;
        while (i < question.length()){
            if (question.charAt(i) < 48 || question.charAt(i) > 57){
                //即不为数字
                arr.add("" + question.charAt(i));
                i++;
            }else{
                //如果是数字,需要判断是不是一个多位数
                StringBuilder tmp = new StringBuilder();
                //判断接着的几个数是不是数字
                while (i < question.length() && question.charAt(i) >=48 && question.charAt(i) <=57){
                    tmp.append(question.charAt(i));
                    i++;
                }
                arr.add(tmp.toString());
            }
        }
        return arr;
    }

    //转换后缀表达式
    public static List<String> toSuffixList(List<String> mid) {
        //定义两个栈
        Stack<String> s1 = new Stack<String>(); // 符号栈
        Stack<String> s2 = new Stack<String>(); // 中间栈
        //开始遍历
        for(String item: mid) {
            if(item.matches("\\d+")) {
                //是数字
                s2.push(item);
            } else if (item.equals("(")) {
                //是左括号
                s1.push(item);
            } else if (item.equals(")")) {
                //是右括号
                while(!s1.peek().equals("(")) {//栈顶不为左括号
                    s2.push(s1.pop());
                }
                //轮到左括号
                s1.pop();
            } else {
                //是操作符
                while(s1.size() != 0 && getPri(s1.peek()) >= getPri(item) ) {
                    //item优先级小于栈顶
                    s2.push(s1.pop());
                }
                //当栈顶的优先级比当前item小时
                s1.push(item);
            }
        }
        //遍历结束
        while(s1.size() != 0) {
            s2.push(s1.pop());
        }
        //倒序返回 创建一个中间栈s3
        Stack<String> s3 = new Stack<>();
        while (s2.size() != 0){
            s3.push(s2.pop());
        }
        ArrayList<String> arr= new ArrayList<>();
        while (s3.size() != 0){
            arr.add(s3.pop());
        }
        return arr;
    }

    //判断优先级
    public static int getPri(String s){
        switch (s){
            case "+":
                return 1;
            case "-":
                return 1;
            case "*":
                return 2;
            case "/":
                return 2;
        }
        return 0;
    }

    //判断是否是操作符
    public static boolean isOper(String val){
        return val.equals("*") || val.equals("/") || val.equals("+") || val.equals("-");
    }

    //对传入的字符串列表进行计算
    public static int figure(List<String> list){
        //后缀表达式的计算逻辑,很简单
        Stack<String> s1 = new Stack<>();
        int num1,num2,tmp;
        for (String s : list) {
            if (isOper(s)){
                // TODO: 2021/12/4 栈顶元素为num2 
                num2 = Integer.parseInt(s1.pop());
                num1 = Integer.parseInt(s1.pop());
                s1.push(calculate(num1,num2,s)+"");
            }else {
                //是数字
                s1.push(s);
            }
        }
        return Integer.parseInt(s1.pop());
    }

    //计算逻辑
    public static int calculate(int num1,int num2, String s){
        switch(s) {
            case "+":
                return num1 + num2;
            case "-":
                return num1 - num2;
            case "*":
                return num1 * num2;
            case "/":
                return num1 / num2;
        }
        //s只可能是以上四种,这里return 0 是为了不报错
        return 0;
    }
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-05 12:17:23  更:2021-12-05 12:18:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:36:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码