【栈】实现逆波兰计算器

本文介绍了栈在计算表达式中的应用,特别是如何使用栈来实现逆波兰计算器。通过数组和链表两种方式模拟栈,详细讲解了从中缀表达式转换为后缀表达式的过程,并提供了完整的代码实现,包括处理括号、支持多种运算符和处理小数值的功能。
摘要由CSDN通过智能技术生成

栈的一个实际需求:
请输入一个表达式
计算式:[722-5+1-5+3-3] 点击计算【如下图】
在这里插入图片描述
请问: 计算机底层是如何运算得到结果的? 注意不是简单的把算式列出运算,因为我们看这个算式 7 * 2 * 2 - 5, 但是计算机怎么理解这个算式的(对计算机而言,它接收到的就是一个字符串),我们讨论的是这个问题 -> 栈

栈的介绍

  • 栈的英文为(stack)
  • 栈是一个先入后出(FILO-First In Last Out)的有序列表。
  • 栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom)。
  • 根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除
  • 出栈(pop)和入栈(push)的概念(如图所示)
    在这里插入图片描述

栈的应用场景

  • 子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。
  • 处理递归调用:和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数、区域变量等数据存入堆栈中。
  • 表达式的转换[中缀表达式转后缀表达式]与求值(实际解决)。
  • 二叉树的遍历。
  • 图的深度优先(depth first)搜索法。

数组模拟栈

由于栈是一种有序列表,就可以使用数组的结构来储存栈的数据内容,模拟栈的出栈,入栈等操作
实现思路分析,并画出示意图
在这里插入图片描述
实现栈的思路分析:

  1. 使用数组来模拟栈
  2. 定义一个 top 表示栈顶,初始化为 -1
  3. 入栈的操作,当有数据加入到栈时,top++; stack[top] = data;
  4. 出栈的操作, int value = stack[top]; top–, return value;

代码实现

package com.atguigu.stack;

import java.util.Scanner;

/**
 * @author Mustang
 * @create 2022-05-07 20:51
 */
public class ArrayStackDemo6 {
   
    public static void main(String[] args) {
   
        ArrayStack6 stack = new ArrayStack6(4);
        String key = "";
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);
        while (loop) {
   
            System.out.println("show: 表示显示栈");
            System.out.println("push: 入栈");
            System.out.println("pop: 出栈");
            System.out.println("exit: 退出程序");
            System.out.println("请输入你的选择:");

            key = scanner.next();
            switch (key) {
   
                case "show":
                    stack.list();
                    break;
                case "push":
                    System.out.println("请输入一个数:");
                    int value = scanner.nextInt();
                    stack.push(value);
                    break;
                case "pop":
                    try {
   
                        int res = stack.pop();
                        System.out.printf("出栈的数据是%d\n", res);
                    } catch (Exception e) {
   
                        System.out.println(e.getMessage());
                    }
                    break;
                case "exit":
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }
    }
}


//定义一个ArrayStack表示栈
class ArrayStack6 {
   

    private int maxSize; //栈的容量大小
    private int[] stack; //数组模拟栈,数据就放在该数组
    private int top = -1; // top表示栈顶,初始化为-1

    public ArrayStack6(int maxSize) {
   
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    //栈满
    public boolean isFull() {
   
        return top == maxSize - 1;
    }

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

    //入栈-push
    public void push(int value) {
   
        if (isFull()) {
   
            System.out.println("栈满~");
            return;
        }
        stack[++top] = value;
    }

    //出栈-pop, 将栈顶的数据返回
    public int pop() {
   
        if (isEmpty()) {
   
            throw new RuntimeException("栈空~");
        }
        //不需要使用单独的一个变量去记录临时的元素,因为数组在重新赋值时会覆盖
        return stack[top--];
    }

    //遍历栈,遍历时,需要从栈顶开始显示数据
    public void list() {
   
        if (isEmpty()) {
   
            System.out.println("栈空~");
            return;
        }
        for (int i = top; i >= 0; i--) {
   
            System.out.printf("stack[%d]=%d\n", i, stack[i]);
        }
    }
}

链表模拟栈

思路:

  • 分别创建节点类,单链表类,栈类
  • 栈类包含3个属性,maxSize容量大小,栈顶top=-1,ssl单链表对象
  • 根据栈类的maxSize大小创建相应长度的单链表
  • 不删除单链表节点,使用覆盖数据域data的方式实现进栈出栈的操作

图解:
在这里插入图片描述

代码实现

package com.atguigu.stack;

import java.util.Scanner;

/**
 * @author Mustang
 * @create 2022-05-07 21:38
 */
public class LinkedListStackDemo7 {
   
    public static void main(String[] args) {
   
        LinkedStack7 stack = new LinkedStack7(3);
        Scanner scanner = new Scanner(System.in);
        String key = "";
        boolean loop = true;
        while (loop) {
   
            System.out.println("show: 显示");
            System.out.println("push: 入栈");
            System.out.println("pop: 出栈");
            System.out.println("exit: 退出程序");
            key = scanner.next();
            switch (key) {
   
                case "show":
                    stack.list();
                    break;
                case "push":
                    System.out.println("请输入数据:");
                    String data = scanner.next();
                    stack.push(data);
                    break;
                case "pop":
                    try {
   
                        stack.pop();
                    } catch (Exception e) {
   
                        System.out.println(e.getMessage());
                    }
                    break;
                case "exit":
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序退出~~");
    }
}

//栈类
class LinkedStack7 {
   

    private int maxSize;
    private SingleLinkedList7 sll;
    private int top = -1;

    public LinkedStack7(int maxSize) {
   
        this.maxSize = maxSize;
        sll = new SingleLinkedList7();
        sll.createLinkedList(maxSize);
    }

    //栈满
    public boolean isFull() {
   
        return top == maxSize - 1;
    }

    //栈空
    public boolean isEmpty() {
   
        return top ==
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值