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

技术标签: 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

智能推荐

Google《Android性能优化》学习笔记_intro and recap timestamps-程序员宅基地

文章浏览阅读1k次。http://www.csdn.net/article/2015-04-15/2824477-android-performance/1摘要:Google在Udacity上的《Android性能优化》在线课程详细介绍了该如何优化性能,这些课程是Google之前在Youtube上发布的Android性能优化典范专题课程的细化与补充。本文是对渲染、运算、内存、电量四个篇章的学习笔记。_intro and recap timestamps

hive使用适用场景_大数据技术中,HIVE的应用场景有哪些-程序员宅基地

文章浏览阅读2k次。事务:之前了解到的是,转账(一个帐户上都加、一个帐户上进行减)行级事务(要保存一条insert\update不会出现只插入一部分的情况)实时:查询速度快,响应速度快。在企业里面,一个请求发送出去,如果不是太复杂的话,在做需求的时候,整个响应过程一般不会超过3SOLTP:一般指的是数据库OLAP:重点在于分析上,用于查询或者分析使用。没有实时要求一般是按天、周、月、年来进行数据统计。OLTP是要求实..._hive 使用场景

Asp.net面试题_asp.net标签必须是小写吗-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏27次。Asp.net核心技术思想 1、概述反射和序列化反射:程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性序列化:序列化是将对象转换为容易传输的格式的过程。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet_asp.net标签必须是小写吗

iphone 把图片保存到Photo Album_iphone file文件放入album-程序员宅基地

文章浏览阅读960次。uikit里有一个函数是UIImageWriteToSavedPhotosAlbum可以实现_iphone file文件放入album

Armv8-A架构安全特性总结_arm sel2技术-程序员宅基地

文章浏览阅读1.2k次。Arm-A 体系架构安全特性总结:安全特性 英文拼写 说明 应对的攻击 引入的版本 XN execute never 不可执行。一般用于配置数据段不可执行,防止数据段注入可执行的shell code。 使用XN可执行DEP(Data execute Prevention,一般我们通常说的堆栈不可执行) 任意地址读写、代码段覆盖 < v8 PXN Privileged Execute Never 特权模式不可执..._arm sel2技术

数据模型的含义是什么?为什么要建立数据模型_什么是数据模型-程序员宅基地

文章浏览阅读9.8k次。数据模型(Data Model)是2113数据特征的5261抽象。数据(Data)是描述事物的符号记录,模型(4102Model)是现实世界的抽象。数据1653模型从抽象层次上描述了系统的静态特征、动态行为和约束条件,为数据库系统的信息表示与操作提供了一个抽象的框架。数据模型所描述的内容有三部分:数据结构、数据操作和数据约束。扩展资料:数据模型所描述的内容包括三个部分:数据结构、数据操作、数据约束。1、数据结构:数据模型中的数据结构主要描述数据的类型、内容、性质以及数据间的联系等。数据结构是数据模型_什么是数据模型

随便推点

WebRTC-Android 源码导读(二):预览实现分析_surfaceviewrenderer-程序员宅基地

文章浏览阅读2.4k次,点赞2次,收藏5次。在本系列第一篇中,我们分析了 WebRTC-Android 相机采集的实现,本文中我们将分析预览的实现。有过一定相机开发经验的朋友可能会疑惑,预览还有什么好分析的,不是直接 camera.setPreviewDisplay 或者 camera.setPreviewTexture 就能在 SurfaceView/TextureView上预览了吗?实际上预览还有更高级的玩法,尤其是需要加上图像处理功能..._surfaceviewrenderer

Easyx-----c语言实现斗地主_easyx制作打牌-程序员宅基地

文章浏览阅读2.7k次,点赞28次,收藏88次。tools.hpp源.cpp_easyx制作打牌

UNITY开发VR从入门到放弃---VR自学手册_unity vr-程序员宅基地

文章浏览阅读2.6w次,点赞54次,收藏349次。如何快速学习VR开发,以及HTCvive的使用。_unity vr

Andorid 屏幕适配_android dpi适配-程序员宅基地

文章浏览阅读188次。1、dpi是什么?2、dp和px转换3、适配策略(宽度百分比,高度长宽比)_android dpi适配

VUE导入项目问题解决办法:找不到依赖此文件夹缺少 ‘node_modules‘。请安装依赖后再尝试导入。_此文件夹缺少 'node_modules'。请安装依赖后再尝试导入。-程序员宅基地

文章浏览阅读1w次,点赞5次,收藏8次。从Gitee上拉取前端项目,导入vue时遇到问题时分析过程_此文件夹缺少 'node_modules'。请安装依赖后再尝试导入。

C语言实现基2DIF-FFT算法(桑德·图基快速傅立叶变换)_桑德图基-程序员宅基地

文章浏览阅读9.1k次,点赞8次,收藏31次。傅立叶变换能将时域信号转换为由sin函数为基底的频域信号,从而我们可以从信号中提取出频率信息或截断频谱简化信号压缩信息。计算机难以处理连续信号。DFT是一种适用于计算机处理的有限信号时频转换方法。DFT用一句话概括,就是将连续信号(频域也是连续函数)经过时域采样(这样会使信号的频域发生周期延拓,得到周期连续的函数,计算机无法处理),再经过频域采样(这样会使时域信号发生周期延拓,时域周期延拓这一步可..._桑德图基

推荐文章

热门文章

相关标签