栈的介绍

  • 栈是限制插入和删除只能在一个位置上进行的线性表。其中,允许插入和删除的一端位于表的末端,叫做栈顶(top),不允许插入和删除的一端叫做栈底(bottom)。对栈的基本操作有push(压栈)和pop(弹栈/出栈),前者向栈顶插入一个元素,后者是删除一个栈顶元素。栈是一种后进先出(LIFO)的数据结构,最先被删除的是最近压栈的元素。

栈实现

  • 由于栈是一个表,因此任何实现表的方法都可以用来实现栈,主要有两种方式,链表实现和数组实现。

链表实现栈-动态栈

  • 可以使用单链表来实现栈。通过在表顶端插入一个元素来实现push,通过删除顶端元素实现pop。
  • 动态栈有链表的部分特性,即元素与元素在物理存储上可以不连续,但是功能受限制,动态栈只能在栈顶进行插入和删除操作,不能在栈底或栈中间进行插入和删除操作。

数组实现栈-静态栈

栈的应用场景

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

静态栈数据结构

package com.acti.stack;

/**
 * author hongyeci
 * date 20220715
 * version 1.0
 * remark 数组实现栈-静态栈 数据结构
 */
public class ArrayStack {
    //栈大小
    private int maxStack;
    //数组模拟栈
    private Object[] stack;
    //栈顶位置-默认为空栈
    private int top = -1;

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

    /**
     * 判断是否空栈
     * @return boolean
     */
    public boolean isEmpty(){
        return this.top == -1;
    }

    /**
     * 判断是否满栈
     * @return boolean
     */
    public boolean isFull(){
        return this.top == this.maxStack-1;
    }

    /**
     * 栈中元素个数
     * @return 元素个数
     */
    public int length(){
        return this.top+1;
    }

    /**
     * 压栈、入栈
     * @param val 入栈元素
     */
    public void push(Object val){
        if (isFull()){
            throw new RuntimeException("此栈已满...");
        }
        top++;
        stack[top] = val;
    }


    /**
     * 弹栈、出栈
     * @return 出栈元素
     */
    public Object pop(){
        if (isEmpty()){
            throw new RuntimeException("空栈,未找到数据...");
        }
        Object value = stack[top];
        top--;
        return value;
    }

    /**
     * 查看栈中的所有元素
     */
    public void stackList(){
        if (isEmpty()){
            throw new RuntimeException("空栈,栈中没有数据...");
        }
        for (int i=0;i<stack.length;i++){
            System.out.printf("stack[%d]=%c\n",i,stack[i]);
        }
    }

    /**
     * 获取栈顶元素
     * @return 返回栈顶元素
     */
    public Object stackTop(){
        return this.stack[top];
    }

}

实例

回文字符串

    /**
     * 判断是否是回文字符串
     * @param val 字符串
     * @return boolean
     */
    public static boolean isPalindromes(String val){
        ArrayStack arrayStack = new ArrayStack(val.length());
        //入栈
        for (int i=0;i<val.length();i++){
            arrayStack.push(val.charAt(i));
        }
        //出栈
        String newVal = "";
        int len = arrayStack.length();
        for (int j=0;j<len;j++){
            newVal += arrayStack.pop();
        }
        return val.equals(newVal);
    }

实现简单计算

package com.acti.stack;

/**
 * author hongyeci
 * date 20220716
 * version 1.0
 * remark 简单计算类 + - * /
 */
public class Calculation {
    /**
     * 计算符号
     */
    private final static char PLUS='+';
    private final static char SUBTRACT='-';
    private final static char MULTIPLY='*';
    private final static char DIVIDE='/';

    /**
     * 判断是否是运算符
     * @param v
     * @return
     */
    public static boolean isOper(char v){
        return PLUS==v || SUBTRACT==v || MULTIPLY==v || DIVIDE==v;
    }

    /**
     * 运算符优先级
     * @param v 运算符字符
     * @return
     */
    public static int priority(char v){
        if (MULTIPLY==v || DIVIDE==v){
            return 1;
        }else if (PLUS==v || SUBTRACT==v){
            return 0;
        }else {
            return -1;
        }
    }

    /**
     * 两数计算
     * @param num1 数字1
     * @param num2 数字2
     * @param v 运算符
     * @return 计算结果
     */
    public static int calculate(int num1,int num2,char v){
        int result = 0;
        switch (v){
            case PLUS:
                result = num2+num1;
                break;
            case SUBTRACT:
                result = num2-num1;
                break;
            case MULTIPLY:
                result = num2*num1;
                break;
            case DIVIDE:
                result = num2/num1;
                break;
            default:
                break;
        }
        return result;
    }
}
/**
     * 静态栈--简单计算
     * @param oper 计算字符串 "33+22-1*5"
     * @return 计算结果
     */
    public static int calculateOper(String oper){
        //初始化数字栈和符号栈
        ArrayStack numStack = new ArrayStack(oper.length());
        ArrayStack symbolStack = new ArrayStack(oper.length());
        int result = 0;
        char symbol = '0';
        int num1 = 0;
        int num2 = 0;
        String str = "";
        for (int i=0;i<oper.length();i++){
            //获取每个字符
            char v = oper.charAt(i);
            //判断是否是运算符--是 则入符号栈
            if (Calculation.isOper(v)){
                numStack.push(str);
                str = "";
                //判断符号栈是否为空
                if(!symbolStack.isEmpty()){
                    //否  判断运算符优先级
                    if (Calculation.priority(v)<=Calculation.priority((Character) symbolStack.stackTop())){
                        //入栈运算符优先级小于等于符号栈中运算符优先级时,先对符号栈中栈顶符号元素及数字栈中两个数字元素进行运算
                        symbol = (char) symbolStack.pop();
                        num1=Integer.parseInt(numStack.pop().toString());
                        num2=Integer.parseInt(numStack.pop().toString());
                        result = Calculation.calculate(num1,num2,symbol);
                        //计算结果入数字栈
                        numStack.push(result);
                    }
                }
                //入栈运算符优先级大于符号栈顶运算符优先级时,直接入栈
                //符号栈为空时,直接入栈
                symbolStack.push(v);
            }else {
                str += v;
                //如果是最后一个数字字符
                if(i==oper.length()-1){
                    numStack.push(str);
                    while (true){
                        if (symbolStack.isEmpty()){
                            break;
                        }
                        num1=Integer.parseInt(numStack.pop().toString());
                        num2=Integer.parseInt(numStack.pop().toString());
                        symbol= (char) symbolStack.pop();
                        result=Calculation.calculate(num1,num2,symbol);
                        numStack.push(result);
                    }
                }

            }
        }
        return Integer.parseInt(numStack.stackTop().toString());
    }

数据结构相关代码仓库地址:
https://gitee.com/red_leafzsp/structureAlgorithms

posted on 2022-07-19 17:27  红叶次  阅读(124)  评论(0)    收藏  举报