栈的应用-综合计数器的实现-程序员宅基地

技术标签: java  数据结构与算法  数据结构  

目录

前言

一、思路分析

二、代码实现

总结

前言

在实现综合计数器之前,大家应该先了解一下什么是前中后缀表达式

前缀、中缀和后缀表达式是表示数学表达式的三种不同方式。

  1. 前缀表达式(也称为波兰式或前缀记法):操作符位于操作数之前。例如,"+ 2 3"表示加法操作,其中2和3是操作数。

  2. 中缀表达式:操作符位于操作数之间。这是我们通常使用的数学表达式表示方式。例如,"2 + 3"表示加法操作,其中2和3是操作数。

  3. 后缀表达式(也称为逆波兰式或后缀记法):操作符位于操作数之后。例如,"2 3 +"表示加法操作,其中2和3是操作数。

这三种表达式都可以表示相同的数学运算,只是操作符和操作数的排列顺序不同。在计算机中,后缀表达式常用于数学表达式的求值,因为它可以通过使用栈来进行简单而高效的计算。

本次实现综合计算器就是借助后缀表达式来实现,为了简单起见,我们并不加入()等的符号


一、思路分析

定义两个栈,一个栈为数栈(NumStack)用来存放数字,另一个栈为符号栈,用来存放符号

1. 通过一个 index  值(索引),来遍历我们的表达式

2. 如果我们发现是一个数字, 就直接入数栈

3. 如果发现扫描到是一个符号,  就分如下情况

  3.1 如果发现当前的符号栈为 空,就直接入栈

  3.2 如果符号栈有操作符,就进行比较,果当前的操作符的优先级小于或者等于栈中的操作符, 就需要从数栈中pop出两个数,在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈, 果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.

4. 当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.

5. 最后在数栈只有一个数字,就是表达式的结果

我们来举个例子 图解 计算 7*2*2-5+1 = 24

二、代码实现

代码量太大,不可能一步一步解析了,上面的过程如果能看懂,并且编程有一定基础,下面代码应该不成问题,代码出处033_尚硅谷_栈实现综合计算器-思路分析(1)_哔哩哔哩_bilibili

大家可以去看看

package 逆波兰计数器;

import StackDemo.StackEmptyException;

import java.util.Arrays;
import java.util.Scanner;

class Test{
    public static void main(String[] args) {
        String str = "7*2*2-5+1";
        ArrayStack numStack = new ArrayStack(10);
        ArrayStack operaStack = new ArrayStack(10);
        String s = "";
        int nums1 = 0;
        int nums2 = 0;
        int index = 0;
        int opera = 0;
        char ch = ' ';
        while (true) {
            ch = str.charAt(index);
            // 判断该字符是否是符号
            if(operaStack.isOpera(ch)){
                // 判断符号栈是否为空
                if(!operaStack.isEmpty()){
                    // 判断优先级
                    if(operaStack.priority(ch) <= operaStack.priority(operaStack.peek())){
                        nums1 = numStack.pop();
                        nums2 = numStack.pop();
                        opera = operaStack.pop();
                        int cal = numStack.cal(nums1, nums2, opera);
                        numStack.push(cal);
                        operaStack.push(ch);
                    }else{
                        operaStack.push(ch);
                    }
                }else{
                    // 符号栈为空,直接入栈
                    operaStack.push(ch);
                }
            }else{
                boolean flag = true;// 定义标志位 检查字符串是否达到末尾

                // 处理非个位数的情况 如 88 66 这样的数
                while (!operaStack.isOpera(ch)) {
                    s+=ch;
                    if(index == str.length() -1 ){
                        numStack.push(Integer.parseInt(s));
                        flag = false;
                        break;
                    }else {
                        index++;
                        ch = str.charAt(index);
                    }
                }
                if(!flag){
                    break;
                }
                numStack.push(Integer.parseInt(s));
                s = "";
                index--;
            }
            index++;
            if(index>=str.length()){
                break;
            }
        }

        while (true) {
            if(operaStack.isEmpty()){
                System.out.println(str+"="+numStack.pop());
                break;
            }
            nums1 = numStack.pop();
            nums2 = numStack.pop();
            opera = operaStack.pop();
            int cal = numStack.cal(nums1, nums2, opera);
            numStack.push(cal);
        }
    }

}



public class ArrayStack {
    private final int capacity;
    private int top = -1;
    private int[] stack ;

    public ArrayStack(int capacity){
        this.capacity = capacity;
        stack = new int[capacity];
    }

    // 入栈
    public void push(int data){
        if(isFull()){
            stack = Arrays.copyOf(stack,capacity*2);
        }
        top++;
        stack[top] = data;
    }

    // 出栈
    public int pop(){
        if(isEmpty()){
            throw new StackEmptyException("队列为空,无法删除元素");
        }

        int value = stack[top];
        top--;
        return value;
    }

    // 查看栈顶的值
    public int peek(){
        return stack[top];
    }

    // 制定优先级规则
    public int priority(int opera){
        if(opera == '*' || opera == '/'){
            return 1;
        }else if(opera == '+' || opera == '-'){
            return 0;
        }else{
            return -1;
        }
    }


    // 判断是否为运算符
    public boolean isOpera(int val){
        return val == '+' || val == '-' || val == '*' || val == '/';
    }

    // 运算方法
    public int cal(int num1,int num2,int opera){
        return  switch (opera) {
            case '+' -> num1 + num2;
            case '-' -> num2 - num1;
            case '*' -> num1 * num2;
            case '/' -> num2 / num1;
            default -> -1;
        };
    }

    public boolean isFull(){
        return top == capacity - 1;
    }
    public boolean isEmpty(){
        return top == - 1;
    }
}

总结

关于栈的应用远不止于此,大家也不必全部了解,只要能运用到这种程度,在刷点面试题,应付面试足矣!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_73869209/article/details/132791952

智能推荐

Chrome 扩展程序——Imagus:图片放大预览工具-程序员宅基地

文章浏览阅读3.3w次,点赞2次,收藏2次。主要介绍 Imagus 的功能及应用,Imagus 是一款简单实用的图片放大预览工具。_imagus

python 描述符_Python黑魔法之描述符-程序员宅基地

文章浏览阅读113次。引言Descriptors(描述符)是Python语言中一个深奥但很重要的一个黑魔法,它被广泛应用于Python语言的内核,熟练掌握描述符将会为Python程序员的工具箱添加一个额外的技巧。本文我将讲述描述符的定义以及一些常见的场景,并且在文末会补充一下__getattr__,__getattribute__,__getitem__这三个同样涉及到属性访问的魔术方法。描述符的定义descr__g..._python revealaccess

jenkins自动化部署及三种构建部署方式_jenkins自动和手动部署-程序员宅基地

文章浏览阅读504次。jenkins自动化部署及三种构建部署方式jenkins是基于java开发的一种持续集成工具,用于监控持续重复的工作,功能包括。1、持续的软件版本发布/测试2、监控外部调用执行项目Jenkins其实很早之前就有了,最近火起来的原因是,大家都在关注devops,关注如何来做持续集成,持续交付,如何来做CI/CD。Jenkins作为持续集成的工具,他其实只是一个平台或者是一个大的框架,它的工作完全就是依靠插件,也就是说你想使用什么功能,你就找到什么样的插件。1.2.jenkins好处1、我在工作中部_jenkins自动和手动部署

GMSK调制解调误码率matlab仿真_gmsk码间干扰-程序员宅基地

文章浏览阅读1.6k次,点赞25次,收藏35次。GMSK(高斯最小频移键控)是一种连续相位的频移键控(CPFSK)调制方法,它在数字通信中得到了广泛应用,特别是在移动通信系统中。GMSK通过限制频率偏差的累积来减少带外辐射,并通过使用高斯滤波器对基带信号进行预调制来平滑相位路径。_gmsk码间干扰

Reader类和Writer类_sreader_writer_uoml-程序员宅基地

文章浏览阅读3k次。从键盘读入用户的输入,并显示在屏幕上1. 效果图2. Java代码package com.example.demo.file;import java.io.InputStreamReader;import java.io.OutputStreamWriter;/** * @Description Reader类和Writer类 * @author 大都督 * @date 2..._sreader_writer_uoml

python编码问题之encode、decode、codecs模块_python中encode在什么模块-程序员宅基地

文章浏览阅读2.1k次。原文链接先说说编解码问题编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。 Eg:str1.decode('gb2312') #将gb2312编码的字符串转换成unicode编码str2.encode('gb2312') #将unicode编码..._python中encode在什么模块

随便推点

extjs中treepanel属性和方法_ext.tree.treepanel 展开节点适应宽度-程序员宅基地

文章浏览阅读363次。树控件由Ext.tree.TreePanel类定义,TreePanel类继承自Panel面板。TreePanel是ExtJS中最多能的组件之一,它非常适合用于展示分层的数据。树的使用是很频繁的,对树节点的各种操作已经和数据库的互动操作,这些都是需要掌握的。_ext.tree.treepanel 展开节点适应宽度

ORACLE常用傻瓜问题1000问-程序员宅基地

文章浏览阅读678次。1. oracle安装完成后的初始口令?  internal/oracle   sys/change_on_install   system/manager   scott/tiger   sysman/oem_temp 2. orACLE9IAS WEB CACHE的初始默认用户和密码? administrator/administrator 3. oracle 8.0.5怎么创建数据库?

iOS UISearchBar改变搜索框的颜色_ios searchbar 设置搜索狂颜色-程序员宅基地

文章浏览阅读2.1k次。[objc] view plain copy //搜索框 - (UISearchBar *)searchBar{ if (_searchBar == nil) { _searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 27, KScreenWidth_ios searchbar 设置搜索狂颜色

ADADELTA AN ADAPTIVE LEARNING RATE METHOD_adadelta一种自适应学习率方法-程序员宅基地

文章浏览阅读527次。ADADELTA: AN ADAPTIVE LEARNING RATE METHOD参考:[自适应学习率调整AdaDelta](https://www.cnblogs.com/neopenx/p/4768388.html)我们提出了一种新的梯度下降的逐维学习率方法ADADELTA。该方法仅使用一阶信息随时间动态地适应,并且除了一般的随机梯度下降外,具有最小的计算开销。该方法不需要人工调整学习速率,对噪声梯度信息、不同模型结构选择、不同数据模式和超参数选择具有鲁棒性。与其他方法相比,我们在分布式集群环境下_adadelta一种自适应学习率方法

从零开始一个微信小程序版知乎_微信小程序开发 知乎-程序员宅基地

文章浏览阅读1.5k次。以前工作没直接进行过小程序的开发,最近闲了下来就赶紧学习一下。因为从零开始,所以没有使用任何框架及UI库,记录一下本次开发中踩过的坑吧~展示效果(界面样式设计与交互来自iOS 4.8.0版本知乎App):动态效果请移步到GitHub查看。一、开始前的准备申请账号:根据小程序注册文档,填写信息和提交相应的资料,就可以拥有自己的小程序帐号。开发工具:微信开发者工具数据来源:Easy M..._微信小程序开发 知乎

centos uwsgi配置_在CentOS 7下安装uwsgi_uwsgi离线安装centos-程序员宅基地

文章浏览阅读153次。https://blog.csdn.net/weixin_35886269/article/details/112941217_uwsgi离线安装centos

推荐文章

热门文章

相关标签