首页 > 其他分享 >栈实现计算器

栈实现计算器

时间:2023-11-25 21:25:09浏览次数:121  
标签:oper 实现 top pop int 计算器 data public

计算器

/**
 * @author 缪广亮
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class Calculator {
    public static void main(String[] args) {
//        完成表达式的运算
        String expression = "770+2*6-4+1";
//        创建数栈和字符栈
        LinkedListStack2 numStack = new LinkedListStack2();
        LinkedListStack2 operationStack = new LinkedListStack2();

        int index = 0;//用于扫描
        int num1 = 0;
        int num2 = 0;
        int operation = ' ';
        int res = 0;
        String keepNum = "";//用于拼接多位数
        char ch = ' ';//用于将每次扫描得到的char保存到ch
//        while循环的扫描expression
        while (true) {
//            依次得到expression的每一个字符
            ch = expression.substring(index, index + 1).charAt(0);
//            判断ch是什么,然后判断
            if (operationStack.isOper(ch)) {//如果是运算符
//                判断当前的符号栈是否为空
                if (!operationStack.isEmpty()) {
//                    如果符号栈有操作符,进行比较,
//                    如果当前的操作符的优先级小于或者等于栈中栈顶的操作符
//                    首先从数栈pop除两个数,再从符号栈pop出一个符号,运算得出结果
//                    最后将当前的操作符入符号栈
                    if (operationStack.priority(ch) <= operationStack.priority((char) operationStack.peek())) {
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                        operation = operationStack.pop();
                        res = numStack.cal(num1, num2, operation);
//                        把运算结果入数栈
                        numStack.push(res);
//                        将当前的操作符入符号栈
                        operationStack.push(ch);
                    } else {
//                        如果当前的操作符的优先级大于栈中的操作符,直接入符号栈
                        operationStack.push(ch);
                    }
                } else {
//                    如果栈为空直接入栈
                    operationStack.push(ch);
                }
            } else {
//                如果是数,直接入数栈
//                numStack.push(ch-48);//得到的是字符'1',而数字1是与字符'1'相差48
//                 当处理多位数时,不能发现是一个数就立即入栈,因为他可能是多位数
//                 在处理数,需要向expression的表达式的index后再看一位,
//                 如果是数就继续进行扫描,如果是符号才入栈
//                定义一个变量字符串,用于拼接
//                处理多位数
                keepNum += ch;
//                如果ch已经是expression的最后一位,直接入栈
                if (index == expression.length() - 1) {
                    numStack.push(Integer.parseInt(keepNum));
                } else {
//                判断下一个字符是不是字符,如果是数字,就继续扫描,如果是运算符则入栈
//                注意看后一位,不是index++
                    if (operationStack.isOper(expression.substring(index + 1, index + 2).charAt(0))) {
//                    如果后一位是运算符。则入栈keepNum="1"/"123"
                        numStack.push(Integer.parseInt(keepNum));
//                    清空keepNum
                        keepNum = "";

                    }
                }
            }
//            index+1,并判断是否扫描到expression最后
            index++;
            if (index >= expression.length())
                break;
        }
//        当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运算
        while (true) {
//            如果符号栈为空,则计算到最后的结果,数栈中只有一个数字即结果
            if (operationStack.isEmpty())
                break;
            num1 = numStack.pop();
            num2 = numStack.pop();
            operation = operationStack.pop();
            res = numStack.cal(num1, num2, operation);
//                        把运算结果入数栈
            numStack.push(res);
        }
//        将数栈的
        System.out.printf("表达式%s = %d", expression, numStack.pop());
    }
}

@SuppressWarnings({"all"})
//链表栈
class LinkedListStack2 {
    private Node top;

    private class Node {
        private int data;
        private Node next;

        public Node(int data) {
            this.data = data;
            this.next = null;
        }
    }

    //  入栈
    public void push(int data) {
        Node newNode = new Node(data);
        if (top == null) {
            top = newNode;
        } else {
            newNode.next = top;
            top = newNode;
        }
    }

    //    出栈
    public int pop() {
        if (top == null) {
            throw new RuntimeException("栈空");
        }
        int data = top.data;
        top = top.next;
        return data;
    }

    //    栈顶元素
    public int peek() {
        if (top == null)
            throw new RuntimeException("栈空");
        return top.data;
    }

    //    栈空
    public boolean isEmpty() {
        return top == null;
    }

    //    遍历
    public void printStack() {
//        top指针不能动,需要一个current的辅助指针
        Node current = top;
        if (top == null)
            throw new RuntimeException("栈空");
        while (current != null) {
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }

    //判断运算符的优先级,用数字代表优先级,数字越大,优先级越高
    public int priority(char oper) {
        if (oper == '*' || oper == '/')
            return 1;
        else if (oper == '+' || oper == '-')
            return 0;
        else
            return -1;//目前的运算符只含有+-*/
    }

    //    判断是不是运算符
    public boolean isOper(char oper) {
        return oper == '*' || oper == '/' || oper == '+' || oper == '-';
    }

    //    计算方法
    public int cal(int num1, int num2, int oper) {
        int res = 0;//计算结果
        switch (oper) {
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num2 - num1;//后pop的数作为被减数,先pop作为减数
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;//后pop的数作为被除数,先pop作为除数
                break;
        }
        return res;
    }
}

标签:oper,实现,top,pop,int,计算器,data,public
From: https://www.cnblogs.com/mglblog/p/17856079.html

相关文章

  • 实现环形进度条效果
    好基友扔过来一张效果图,简单分析下,一起看看如何实现它吧。一个半环形用于表示0-100%。半环形开头有一个圆点作为修饰。半环形两端需要呈现为圆角。通过div实现先画一个长方形。<divclass="graph"></div>.graph{width:200px;height:100px;border:20pxsolidrgb......
  • 基于FFmpeg和Qt实现简易视频播放器
    VideoPlay001记得一键三连哦使用qt+ffmpeg开发简单的视频播放器,无声音视频解码使用的是软解码即只用CPU进行QPainter绘制每一帧图像,CPU占用过高简单易学,适合小白入门学习FFMpeg视频解析的基本API遗留问题视频播放时间的处理,基匀速播放的实现原理项目代码videoPl......
  • 迭代器手写实现
    迭代器实现首先,实现接口Iterable其次,重写iterate方法,该方法返回类型又是一个迭代器,所有直接new。新new的迭代器采用匿名内部类,其中有两个方法:hasnext和next。这里因为需要迭代的对象是数组,通过索引即可获取数组每个元素。最后测试,使用foreach,其内部就是一个迭代器,会自动访问......
  • 《信息安全系统设计与实现》第十二周学习笔记
    《信息安全系统设计与实现》第十二周学习笔记第13章TCP/IP和网络编程TCP/IP协议TCP/IP协议是利用IP进行通信时所必须用到的协议群的统称。具体来说,IP或ICMP、TCP或UDP、TELNET或FTP、以及HTTP等都属于TCP/IP协议。他们与TCP或IP的关系紧密,是互联网必不可少的......
  • JavaWeb中的文件上传和下载功能的实现
    导入相关支持jar包:commons-fileupload.jar,commons-io.jar对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件......
  • 空间三维模型的编码结构光方法实现:基于EinScan-S软件
      本文介绍基于EinScan-S软件,实现编码结构光方法的空间三维模型重建的具体操作。目录1相关原理1.1编码结构光成像原理1.2编码结构光编码方式1.3编码结构光与侧影轮廓方法比较1.4编码结构光方法流程2三维模型制作2.1防晒霜罐三维模型制作2.1.1前期准备工作2.1.2软件配......
  • 信息安全系统设计与实现 学习笔记11
    《Unix/Linux系统编程》13章学习笔记网络编程简介TCP/IP协议、UDP和TCP协议、服务器—客户机计算、HTTP和Web页面、动态Web页面的PHP和CGI编程TCP/IP协议TCP/IP是互联网的基础,TCP代表传输控制协议,IP代表互联网协议。TCP/IP的组织结构分为几个层级,通常称为TCP/IP堆栈。顶层时......
  • PyTorch团队重写「分割一切」模型,比原始实现快8倍
    前言 我们该如何优化Meta的「分割一切」模型,PyTorch团队撰写的这篇博客由浅入深的帮你解答。本文转载自机器之心仅用于学术分享,若侵权请联系删除欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结、最新技术跟踪、经典论文解读、CV招聘信息。CV各大方向专栏与各个部署......
  • JavaWeb实现文件上传和下载
    环境配置:导入依赖jar包。commons-fileupload-1.4.jarcommons-io-2.6.jar上传表单的enctype属性enctype属性规定在发送到服务器之前应该如何对表单数据进行编码。语法<formenctype="value">1属性值值 描述application/x-www-form-urlencoded 在发送前编码所有字符(默认)multi......
  • Java 反射+递归 实现数据聚合发布的配置化
    大致是GraphQL的思路分开配置接口数据结构和数据实体的元数据支持列表查询,支持多层级的数据聚合参数选叶子节点就行,后续可以把参数用JS实现一个选择树状结构的UI,生成出查询字符串来,或者按照字段分配权限给租户异常处理的不太好,有待继续调试不支持数据权限,只支持根据聚合根向......