Java栈结构的基本实现&前缀,中缀,后缀表达式的转化和计算

判断栈是否为空:
public boolean isEmpty() {
    return topIndex == -1;
}
判断栈是否已满:
public boolean isFull() {
    return topIndex == maxSize - 1;
}
向栈中压入元素:
public void push(T element) {
    if (isFull())
        throw new StackFullException("栈满了");
    elementData[++topIndex] = element;
}
从栈中弹出元素:
public T pop() {
    if (isEmpty())
        throw new StackEmptyException("我为空,不弹出");
    return (T) elementData[topIndex--];
}
查看栈顶元素:
public T peekTop() {
    return (T) elementData[topIndex];
}
重写toString方法:
@Override
public String toString() {
    if (isEmpty())
        return "[]";
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("[");
    for (int i = topIndex; ; i--) {
        stringBuilder.append(elementData[i]);
        if (i == 0) {
            return stringBuilder.append("]").toString();
        }
    }
}

栈的基本代码汇总:

package com.xm;

import com.exception.StackEmptyException;
import com.exception.StackFullException;

public class ArrayStack<T> {

    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        elementData = (T[]) new Object[this.maxSize];
        this.topIndex = -1;
    }

    private int topIndex;
    private int maxSize;
    private T[] elementData;

    public boolean isEmpty() {
        return topIndex == -1;
    }

    public boolean isFull() {
        return topIndex == maxSize - 1;
    }

    public void push(T element) {
        if (isFull())
            throw new StackFullException("栈满了");
        elementData[++topIndex] = element;
    }

    public T pop() {
        if (isEmpty())
            throw new StackEmptyException("我为空,不弹出");
        return (T) elementData[topIndex--];
    }

    public T peekTop() {
        return (T) elementData[topIndex];
    }

    @Override
    public String toString() {
        if (isEmpty())
            return "[]";
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[");
        for (int i = topIndex; ; i--) {
            stringBuilder.append(elementData[i]);
            if (i == 0) {
                return stringBuilder.append("]").toString();
            }
        }
    }
}

栈实现字符串中缀表达式运算:

栈实现字符串中缀表达式运算的要点:
  1. 如果发现读入的字符内容是数值,直接存储到数字栈中

  2. 如果读入的字符是一个符号

    • 如果符号栈中没有任何内容,那么直接存入到符号栈中

    • 如果符号栈中已经有运算符,那么当前的字符和符号栈中的栈顶字符进行比较,若当前的运算符小于栈中的运算符,则需要从数字栈中弹出两个数值,再从符号栈中弹出一个运算符进行算术计算得到结果,并将结果保存在数字栈中,然后将当前的运算符推入符号栈

    • 如果当前的符号运算的优先级大于等于符号栈中已有的运算符,那么当前的符号入栈

  3. 当表达式字符串整体扫描完成,就顺序的从数字栈和符号栈中弹出相应的数字和运算符,进行计算,并将结果存入数字栈,(当符号栈为空时,停止计算)

  4. 最后的结果存放在数字栈中;

package com.xm;

import com.exception.IllegalOperatorException;
import org.junit.Test;

import java.util.Scanner;

public class MiddleTest {
    public static boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/';
    }

    public static int getPriority(char c) {
        switch (c) {
            case '*':
            case '/':
                return 1;
            case '-':
            case '+':
                return 0;
            default:
                return -1;
        }
    }

    public static int getPriority(String c) {
        switch (c) {
            case "*":
            case "/":
                return 2;
            case "+":
            case "-":
                return 1;
            default:
                return -1;
        }
    }

    public static int doCalculate(char opera, int num1, int num2) {
        switch (opera) {
            case '+':
                return num1 + num2;
            case '-':
                return num1 - num2;
            case '*':
                return num1 * num2;
            case '/':
                return num1 / num2;
            default:
                throw new IllegalOperatorException("无效运算符");
        }
    }

    @Test
    public void test() {
        Scanner input = new Scanner(System.in);
        ArrayStack<Integer> num = new ArrayStack<>(20);
        ArrayStack<Character> symbol = new ArrayStack<>(20);
        //String exp = input.next();
        String exp = "2+1+7*10+7/5";
        /*
         * 局部变量 存储临时计算值
         */
        int num1;
        int num2;
        /*
         * 临时变量存储操作数
         */
        char operator = 0;
        String operators = "";
        /*
         * 临时表达式的结果
         */
        int tempResult = 0;
        /*
         *字符串下标索引
         */
        int index = 0;
        /*
         * 遍历到的当前字符
         */
        char currentChar = 0;
        char currentString = 0;
        String appendNumber = "";
        for (int expIndex = 0; expIndex < exp.length(); expIndex++) {
            currentChar = exp.charAt(expIndex);
            if (isOperator(currentChar)) {
                if (symbol.isEmpty() || getPriority(currentChar) >= getPriority(symbol.peekTop()))
                    symbol.push(currentChar);
                else {
                    num2 = num.pop();
                    num1 = num.pop();
                    operator = symbol.pop();
                    tempResult = MiddleTest.doCalculate(operator, num1, num2);
                    num.push(tempResult);
                    symbol.push(currentChar);

                }
            }
            else {
//                num.push(Integer.parseInt(String.valueOf(currentChar)));
//                num.push(currentChar - '0');
                appendNumber += currentChar;
                if (expIndex == exp.length() - 1) {
                    num.push(Integer.valueOf(appendNumber));
                }
                else if (isOperator(exp.charAt(expIndex + 1))) {
                    num.push(Integer.valueOf(appendNumber));
                    appendNumber = "";
                }

            }
        }
        while (!symbol.isEmpty()) {
            num2 = num.pop();
            num1 = num.pop();
            operator = symbol.pop();
            tempResult = MiddleTest.doCalculate(operator, num1, num2);
            num.push(tempResult);
        }
        System.out.println("表达式:" + exp);
        System.out.println("计算结果:" + num.pop());
    }
}

栈实现前缀表达式计算

package com.xm;

/**
 * BeforeTest: 前缀表达式计算
 * 思路:从后往前入栈,遇到运算符计算后入栈
 *
 * @author IlffQ
 * 2022/7/29
 */
public class BeforeTest {

    public static void main(String[] args) {
        ArrayStack<Integer> numStack = new ArrayStack(40);
        String exp = "-*+1234";
        for (int expIndex = exp.length() - 1; expIndex >= 0; expIndex--) {
            char currentChar = exp.charAt(expIndex);
            if (!MiddleTest.isOperator(currentChar))
                numStack.push(currentChar - '0');
            else {
                int num1 = numStack.pop();
                int num2 = numStack.pop();
                numStack.push(MiddleTest.doCalculate(currentChar, num1, num2));
            }
        }
        System.out.println(numStack.pop());
    }
}

栈实现后缀表达式计算(个位运算)

package com.xm;

/**
 * afterTest:
 *
 * @author IlffQ
 * 2022/7/29
 */
public class AfterTest {
    public static void main(String[] args) {
        ArrayStack<Integer> numStack = new ArrayStack(40);
        String exp = "56+7*8-";
        for (int expIndex = 0; expIndex < exp.length(); expIndex++) {
            char currentChar = exp.charAt(expIndex);
            if (!MiddleTest.isOperator(currentChar))
                numStack.push(currentChar - '0');
            else {
                int num2 = numStack.pop();
                int num1 = numStack.pop();
                numStack.push(MiddleTest.doCalculate(currentChar, num1, num2));
            }
        }
        System.out.println(numStack.pop());
    }
}

栈实现后缀表达式的计算(多位数运算)

package com.util;

import com.xm.ArrayStack;
import com.xm.MiddleTest;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * SuffixExpressionUtil:
 *
 * @author IlffQ
 * 2022/7/29
 */
public class SuffixExpressionUtil {
    public static int calculator(String expression, String splitSign) {
        List<String> expressionList = getExpressionList(expression, splitSign);
        ArrayStack<Integer> numStack = new ArrayStack<>(40);
        for (String str : expressionList) {
            if (str.matches("\\d+")) {
                numStack.push(Integer.valueOf(str));
            }
            else {
                int num2 = numStack.pop();
                int num1 = numStack.pop();
                numStack.push(MiddleTest.doCalculate(str.charAt(0), num1, num2));
            }
        }
        return numStack.pop();
    }

    private static List<String> getExpressionList(String expression, String splitSign) {
        String[] strings = expression.split(splitSign);
        List<String> expressionList = new ArrayList<>();
        expressionList.addAll(Arrays.asList(strings));
        return expressionList;
    }
}

测试类

package com.xm;

import com.util.SuffixExpressionUtil;

/**
 * SuffixExpressionTest:  后缀表达式多位数计算
 *
 * @author IlffQ
 * 2022/7/29
 */
public class SuffixExpressionTest {
    public static void main(String[] args) {
        String exp="52 61 + 17 * 28 -";
        int result= SuffixExpressionUtil.calculator(exp," ");
        System.out.println(result);
    }
}

栈实现中缀表达式到后缀表达式的转化,并实现计算

中缀表达式转化位后缀表达式的要点:
  1. 首先要创建两个栈。
  • a :一个栈用于储存字符串。记为S1
  • b:一个栈用于存储雷士的计算结果,记为S2(实际用ArrayList代替更好)
  1. 从左向右遍历中缀表达式
  • a:遇到操作数直接压入S2栈
  • b:遇到运算符的时候比较其和S1栈顶运算符的优先级
      1. 如果S1栈为空,或栈顶运算符为左括号,则直接将此运算符入栈S1。
      2. 如果当前运算符的优先级高于栈顶运算符,也将当前运算符入栈S1。
      3. 否则将S1栈顶的运算符弹出并压入栈S2中,再次转到过程2,和新的栈顶运算符比较
  1. 遇到括号时
  • a:如果是左括号,则直接压入S1
  • b:如果是右括号,则依次弹出S1的栈顶运算符,直到遇到左括号为止,此时将这一对括号丢弃。
  1. 重复过程2和过程3,直到遍历完成中缀表达式list
  2. 将栈S1中剩余的运算符依次弹出并压入S2栈。
  3. 依次弹出栈S2中元素,并组装成数组,数组的倒序就是中缀表达式对应的后缀表达式(栈S2若直接使用ArrayList这一步可以省略,因为ArrayList中元素的顺序就是后缀表达式的顺序)
package com.util;

import com.xm.MiddleTest;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * InfixExpressionUtil:
 *
 * @author IlffQ
 * 2022/7/29
 */
public class InfixExpressionUtil {
    /**
     * 中缀表达式转换为后缀表达式
     */
    public static String toSuffixExpression(String exp) {
        List<String> infixExpressionList = toInfixExpressionList(exp);
        List<String> suffixExpressionList = toSuffixExpressionList(infixExpressionList);
        StringBuilder suffixExpression = new StringBuilder();
        for (int i = 0; ; i++) {
            suffixExpression.append(suffixExpressionList.get(i));
            if (i == suffixExpressionList.size() - 1) {
                return suffixExpression.toString();
            }
            suffixExpression.append(" ");
        }
    }

    /**
     * 将中缀list转化为后缀表达式list
     */
    private static List<String> toSuffixExpressionList(List<String> infixExpressionList) {
        Stack<String> s1 = new Stack<>();
        List<String> s2 = new ArrayList<>();
        for (String item : infixExpressionList) {

            if (item.matches("\\d+")) {
                s2.add(item);
            }
            else if (item.equals("(")) {
                s1.push(item);
            }
            else if (item.equals(")")) {
                while (!s1.peek().equals("(")) {
                    s2.add(s1.pop());
                }
                s1.pop();
            }
            else {
                while (s1.size() != 0 && (MiddleTest.getPriority(s1.peek()) >= MiddleTest.getPriority(item))) {
                    s2.add(s1.pop());
                }
                s1.push(item);
            }

        }
        while (s1.size() != 0) {
            s2.add(s1.pop());
        }
        return s2;
    }

    /**
     * 中缀表达式转换为中中缀list
     */
    private static List<String> toInfixExpressionList(String exp) {
        ArrayList<String> listResult = new ArrayList<>();
        int expIndex = 0;
        String tempAppend = "";
        char currentChar;
        do {
            //判断当前元素是数字还是运算符
            if (isOperator(currentChar = exp.charAt(expIndex))) {
                listResult.add(String.valueOf(currentChar));
                expIndex++;
            }
            else {
                tempAppend = "";
                while (expIndex < exp.length() && !isOperator(currentChar = exp.charAt(expIndex))) {
                    tempAppend += currentChar;

                    expIndex++;
                }
                listResult.add(tempAppend);
            }
        } while (expIndex < exp.length());
        return listResult;
    }

    private static boolean isOperator(char c) {
        return c < 48 || c > 57;
    }
}

测试类

package com.xm;

import com.util.InfixExpressionUtil;
import com.util.SuffixExpressionUtil;

/**
 * InfixExpressionTest:
 *
 * @author IlffQ
 * 2022/7/29
 */
public class InfixExpressionTest {
    public static void main(String[] args) {
        String exp="1+((22+3)*4)-5";
        String suffixExpression = InfixExpressionUtil.toSuffixExpression(exp);
        System.out.println(suffixExpression);
        int calculator = SuffixExpressionUtil.calculator(suffixExpression, " ");
        System.out.println(calculator);
    }
}

输出:

后缀表达式:1 22 3 + 4 * + 5 -
计算结果:96
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ILFFQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值