4.1到4.5-栈的概述以及利用栈实现简单的计算器

4-栈

4.1-栈的实际需求:输入表达式并计算

比如我们输入一个表达式,那么计算机是怎么计算的呢?他怎么知道加减乘除的顺序呢?首先我们要明白的一点是,对于计算机而言,我们输入的表达式,其实是一个字符串,那么计算机在识别表达式并计算的过程中,就使用到了栈

4.2-栈的介绍(stack)

  • 栈是操作受限的线性表,操作受限的意思是,栈的取出和压入都只能在一端进行,所以造成的结果就是元素的先进后出,而线性表是指栈中元素之间的逻辑关系是一对一的
  • 允许插入和删除的一端,称之为栈顶,而固定无法操作的一端,称之为栈底
  • 出栈pop
  • 入栈push
  • 返回栈顶元素peek

4.3-栈的应用场景

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

4.4-栈的快速入门:数组模拟栈分析和实现

  • 实现栈的思路分析
    1. 使用数组模拟栈
    2. 定义top变量表示栈顶,初始化为-1
    3. 入栈操作:当有数据加入到栈的时候,stack[++top] = data;
    4. 出栈操作:return stack[top–];
package com.hejiale.Stack.v1;

/**
 * 定义一个stack,表示栈
 */
public class ArrayStack {
    private int maxSize ;//栈的大小
    private int[] stack;//数组,用数组模拟栈,数据就放到该数组中
    private int top = -1;//指向栈顶的数据,初始化为-1表示没有数据

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

    //判断栈满
    public boolean isFull(){
        // top初始值为-1,每加入一个元素,top会先加1,所以当top等于数组的容量的时候,栈满,因为数组下标从0开始,所以
        //top == maxSize - 1;
        return top == maxSize - 1;
    }
    //判断栈空
    public boolean isEmpty(){
        return top == -1;
    }
    //入栈
    public void push(int value){
        if (isFull()){
            System.out.println("栈满,不能入栈");
            return;
        }
        stack[++top] = value;
    }
    //出栈
    public int pop(){
        if (isEmpty()){
            throw new RuntimeException("栈空,不能出栈");
        }
        return stack[top--];
    }

    //遍历栈,遍历的时候,需要从栈顶开始显示数据
    public void list(){
        if (isEmpty()){
            System.out.println("栈空,没有数据");
        }
        for (int i = top ; i>=0;i--){
            System.out.print(stack[i]+"  ");
        }
    }
}

4.5-栈实现综合计算器:完成表达式的计算

  • 表达式只包含±*/运算符
  • ArrayStack中添加以下方法
//返回运算符的优先级,优先级是程序员定的,优先级越高,返回的数字越大
public int priority(int oper) {
    if (oper == '*' || oper == '/') {
        return 1;
    } else if (oper == '+' || oper == '-') {
        return 0;
    } else {
        return -1;
    }
}

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

/**
* 计算方法
*  注意:
*      次顶元素 操作符 栈顶元素
* @param num1 栈顶元素
* @param num2 次顶元素
* @param oper 操作符
* @return
*/
public int cal(int num1, int num2, int oper) {
    int res = 0;//存放计算的结果
    switch (oper) {
        case '+':
            res = num2 + num1;
            break;
        case '-':
            res = num2 - num1;
            break;
        case '*':
            res = num2 * num1;
            break;
        case '/':
            res = num2 / num1;
            break;
        default:
            break;
    }
    return res;
}
package com.hejiale.Stack.v2;

/**
 * 用栈,实现简单的表达式计算,即表达式的运算符只有+ - * /
 */
public class Calculator {
    public static void main(String[] args) {
        String expressing = "7+2*6-4";
        //1. 首先,准备两个栈,一个数栈,一个符号栈
        ArrayStack numberStack = new ArrayStack(10);//数栈
        ArrayStack operStack = new ArrayStack(10);//符号栈
        //2. 定义需要的辅助遍历
        int index = 0;//扫描字符串用到的索引
        int num1 = 0;//用来保存栈顶元素
        int num2 = 0;//用来保存次顶元素
        int oper = 0;//用来保存符号栈返回的符号
        int res = 0;//用来保存计算结果
        char ch = ' ';//将每次扫描得到的char保存到ch中
        //3. 开始扫描
        while (true) {
            //依次得到expression的每个字符
            ch = expressing.charAt(index++);
            //判断ch是数字还是符号
            if (operStack.isOper(ch)) {
                /*
                    如果ch是符号,则先判断当前符号栈是否为空
                    如果为空,直接入栈
                    如果不为空,则依次弹出符号栈中,优先级大于等于当前运算符的运算符,并计算,然后将计算结果压入数栈中
                */
                if (!operStack.isEmpty()) {//如果不为空
                    while(true){
                        //得到栈顶元素,注意不是出栈pop,仅仅是得到栈顶元素peak
                        /*
                            这里出错:出错原因是没有分析operStack为空的情况,因为我认为while循环上一句的if语句
                            已经判断不为空才进入while循环,所以可以不分析为空的情况,这是不对的,因为如果我们栈中的操作符
                            都大于当前操作符,那么我们依次弹出符号栈中的全部符号,那么这个时候,如果不进行判空操作的话
                            我们的operStack.peek()操作就会报越界异常

                            所以,以后的开发中,一定要考虑全面,时刻注意是否会出现为null的情况,尤其是在if语句中
                            包含while语句的时候
                        */
                        if(operStack.isEmpty()){
                            operStack.push(ch);
                            break;
                        }else if(operStack.priority(operStack.peek())>=operStack.priority(ch)){
                            oper = operStack.pop();
                            num1 = numberStack.pop();//栈顶元素
                            num2 = numberStack.pop();//次顶元素
                            res = operStack.cal(num1, num2, oper);//计算并得到结果
                            numberStack.push(res);//将结果入数栈
                        }else {
                            operStack.push(ch);
                            break;
                        }
                        /*if(operStack.priority(operStack.peek())>=operStack.priority(ch)){
                            oper = operStack.pop();
                            num1 = numberStack.pop();//栈顶元素
                            num2 = numberStack.pop();//次顶元素
                            res = operStack.cal(num1, num2, oper);//计算并得到结果
                            numberStack.push(res);//将结果入数栈
                        }else {
                            operStack.push(ch);
                            break;
                        }*/
                    }
                } else {//如果为空
                    operStack.push(ch);//将扫描到的运算符入栈
                }
            }else {
                numberStack.push(ch - 48);
            }
            //当表达式扫描完后,结束while循环,但是计算还没有完成,因为有可能符号栈不为空
            if(index == expressing.length()){
                break;
            }
        }
        while (true){
            if (operStack.isEmpty()){
                break;
            }
            oper = operStack.pop();
            num1 = numberStack.pop();//栈顶元素
            num2 = numberStack.pop();//次顶元素
            res = operStack.cal(num1, num2, oper);//计算并得到结果
            numberStack.push(res);//将结果入数栈
        }
        System.out.println(numberStack.pop());
    }
}

这里只是实现了一个简单的表达式计算
1. ()等界限符待加入
2. 多位数字的计算待加入,因为当前的程序每次扫描一位字符就进行判断,所以只可以实现个位数的计算

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REaDME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值