美文网首页
数据结构入门教程-栈的应用实例1

数据结构入门教程-栈的应用实例1

作者: 会上树的程序猿 | 来源:发表于2020-02-01 12:21 被阅读0次

在这篇文章中数据结构入门教程-栈,我们了解了栈的基本操作,如入栈(push)和出栈(pop)这两个重要的特性,本篇我们来说说栈的应用实例

需求
  • 我们利用栈的特点来实现表达式6+2*6-3的计算

当然我们可以直接利用计算机来得出该表达式的结果,这里只是简单的表达式,说白了,我们来实现计算器的简单计算功能,因为我们的表达式中既有数字也有运算符,因此示意图如下:

微信截图_20200201120143.png

这是我的图,我需要两个栈分别用来保存数字和操作符,下面简单的分析下思路

  • 首先我们需要一个指针index也就是图中所示,index主要用来遍历我们的表达式
  • 如果遍历的过程是数字,那么直接入数栈即可
  • 如果遍历的过程中是操作符,需要分情况判断:
  • 1.1 如果当前符号栈为null,就直接入栈
  • 1.2 如果当前符号栈中不为null,首先就行比较,如果当前操作符的优先级小于等于符号栈中的操作符,此时需要我们从数栈中pop两个数,同时从符号栈中pop一个操作符,接着进行计算,将得到的结果入数栈,将当前的操作符入符号栈.
  • 1.3 如果当前的操作符大于符号栈中的操作符,那么直接入符号栈即可
  • 当我们的表达式扫描完成时,顺序从数栈和符号栈中pop对应的数和符号,就行计算.
  • 那么最后在数栈中的数字就是我们最终所得的结果.

接着我们来看代码实现

代码实现
  • 首先我们创建栈和常用的方法
 //定义栈结构类
class ArrayStack {
private int maxSize; //表示栈的最大容量
private int[] stack; //stack实际用来保存数据的
private int top = -1; //top表示栈顶,初始值为-1,表示此时栈中是没有数据的

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

//栈满的条件
public boolean isFull(){
    return top == maxSize -1;
}
//栈空的条件
public boolean isEmpty(){
    return top == -1;
}
//返回栈顶的值,但不自增
public int peek(){
    return stack[top];
}
//入栈操作
public void push(int element){
    if (isFull()){
        throw new ArrayIndexOutOfBoundsException("栈已经满了~");
    }
    top ++;
    stack[top] = element;
}
//出栈操作
public int pop(){
    if (isEmpty()){
        throw new RuntimeException("栈空~");
    }
    int element = stack[top];
    top --;
    return element;
}
//打印操作
public void print(){
    if (isEmpty()){
        System.out.println("栈空~");
        return;
    }
    for (int i = top; i >= 0 ; i--) {

        System.out.printf("stack[%d]=%d\n",i,stack[i]);
    }

}


//返回操作符的优先级,这里规定乘除的优先级为1,加减为0

/**
 *
 * @param optional 传入的操作符
 * @return
 */
public int priority(int optional){
    if (optional == '*' || optional == '/'){
        return 1;
    }
    if (optional == '+' || optional == '-'){
        return 0;
    }else {
        return -1; //这里的操作符默认W为+ - * /这四种.
    }
}
//判断是否是一个操作符
public boolean isOper(char value){
    return value == '+'|| value == '-' || value == '*'|| value == '/';
}
//计算方法

/**
 *
 * @param num1 数字num1
 * @param num2 数字num2
 * @param oper 操作符包括(+ - * /)
 * @return
 */
public int cal(int num1,int num2,int oper){
    //定义一个临时的变量用来存放计算的结果值,默认为0
    int result = 0;
    switch (oper){

        case '+':
            result = num1 + num2;
            break;
        case '-':
            result = num2 - num1;
            break;
        case '*':
            result = num1 * num2;
            break;
        case '/':
            result = num2 / num1;
            break;
        default:
            break;
    }
    return result;
  }
}

上述是我们栈的定义,其中里面的方法最重要的是计算方法和操作符的判断的方法,代码简单这里不多说了,接着我们看测试代码:

测试代码
public class Calculator {

public static void main(String[] args) {
    //计算表达式
    String expression = "56+2*6-3";
    //分别创建数栈和操作符栈
    ArrayStack numStack = new ArrayStack(10);
    ArrayStack operStack = new ArrayStack(10);
    //定义相关需要的临时变量
    int index = 0; //用于遍历expression的指针
    int num1 = 0; //用于存储从数栈中取出的第一个计算的数字
    int num2 = 0; //用于存储从数栈中取出的第二个计算的数字
    int oper = 0 ; //临时存储从operStack中取出计算的操作符
    int result = 0; //保存我们的计算的结果值
    char ch = ' '; //临时存储从expression中的分割的每一个字符
    String keepNum = ""; //用于拼接多位数的字符

    //循环扫描expression
    while (true){
        //substring(index,index+1) 获取当前index的位置的字符串, charAt(0)转为对应的字符
        ch = expression.substring(index,index+1).charAt(0);
        //判断ch是什么,然后进行相应的处理
        if (operStack.isOper(ch)){ //如果是操作符
            //判断当前符号栈是否为null
            if (!operStack.isEmpty()){ //不为null
                //首先进行比较,如果当前操作符的优先级小于等于operStack中:
                //1. 从numStack取出两个数字
                //1.1. 从operStack中去取出操作符
                //1.2.进行计算,然后将结果入numStack,将当前比较的操作符入operStack即可
                if (operStack.priority(ch) <= operStack.priority(operStack.peek())){
                    num1 = numStack.pop(); //获取第一个计算的数字
                    num2 = numStack.pop(); //获取第二个计算的数字
                    oper = operStack.pop(); //从字符栈中获取操作符
                    //进行计算
                    result = numStack.cal(num1,num2,oper);
                    //将result保存到numStack中
                    numStack.push(result);
                    //将当前的操作符入栈
                    operStack.push(ch);
                }else {
                    //如果当前的操作符的优先级大于operStack中的优先级,直接入栈
                    operStack.push(ch);
                }

            }else {
                //如果当前operStack为null,直接入栈即可
                operStack.push(ch);
            }

        }else {
            //处理多位数字时:
            //1. 不能一扫描到数字就入栈,可能后面还是数字,所以需要我们的index继续向后移动一位,如果时候操作符的话可以入栈了
            keepNum += ch;
            //判断是否已经是expression的最后一个
            if (index == expression.length()-1){
                numStack.push(Integer.parseInt(keepNum));
            }else {
                //判断下一个字符是否是数字,如果是数字的话继续扫描,如果是操作符的话直接入栈
                //index+1 和index+2表示向后看一位不等于index++
                if (operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))) {
                    //入栈
                    numStack.push(Integer.parseInt(keepNum));
                    //注意:将原先的keepNum的值清空
                    keepNum = "";
                }
            }
        }
        //让index +1,判断是否扫描到了expression的最后expression
        index ++;
        if (index >= expression.length()){
            break;
        }
    }
    //当扫描完成时,就顺序从numStack和operStack取出值进行计算操作
    while (true){
        //当我们的operStack中没有了操作符时,就表示我们的numStack中只有一个数字那就是最后的计算结果result
        if (operStack.isEmpty()){
            break;
        }
        num1 = numStack.pop(); //获取第一个计算的数字
        num2 = numStack.pop(); //获取第二个计算的数字
        oper = operStack.pop(); //从字符栈中获取操作符
        //进行计算
        result = numStack.cal(num1,num2,oper);
        //将result保存到numStack中
        numStack.push(result);
    }
    System.out.printf("表达式%s = %d",expression,numStack.pop());
}

来看测试结果如下图:

测试结果.png

从上述结果可以看出时没有问题的,本节所讲的是利用栈实现中缀表达式的计算,关于中缀表达式可以自己百度找找相关资料

相关文章

  • 数据结构入门教程-栈的应用实例1

    在这篇文章中数据结构入门教程-栈,我们了解了栈的基本操作,如入栈(push)和出栈(pop)这两个重要的特性,本篇...

  • 队列和栈的应用

    队列和栈的使用 标签(空格分隔): algorithm 队列和栈的应用 1.队列的应用 队列是一种常见的数据结构,...

  • React 入门的一些文章

    React 入门实例教程 Redux 入门教程(一):基本用法 Redux 的设计思想很简单 (1)Web 应用是...

  • 文章结构 栈是什么 Java中的Stack源码分析 什么时候使用栈 应用实例:使用栈来解决表达式计算问题 1、栈是...

  • 数据结构

    数据结构 1. 栈 先进后出 栈顶,栈底 应用:浏览器的后退按钮 实现一个栈: Stack() 创建一个新的空栈。...

  • 栈和队列

    栈和队列是两种应用非常广泛的数据结构,它们都来自线性表数据结构,都是“操作受限”的线性表。 栈 栈(Stack):...

  • 004 go语言实现栈

    1 数据结构 数据结构: 要实现的功能:0 栈的初始化1 获取栈长度2 入栈3 出栈4 清空栈内容5 判断栈是否为...

  • 数据结构与算法掌握这些就够了

    数据结构 线性结构数组、链表、栈、队列 非线性多维数组、树、图 1. 栈 后进先出,可以处理递归调用实际应用:字符...

  • 微服务架构设计模式(十)微服务的部署

    部署微服务应用 1、将服务部署为容器 (1)总体部署步骤 (2)容器化的优势 封装技术栈 服务实例隔离 实例资源受...

  • 栈和队列

    1、栈 栈是一种先进先出的数据结构。栈顶进栈,栈顶出栈。 数据结构 栈的初始化 进栈 出栈 栈的最小值 2、队列 ...

网友评论

      本文标题:数据结构入门教程-栈的应用实例1

      本文链接:https://www.haomeiwen.com/subject/yrkgthtx.html