栈
- 栈
- 判断栈是否为空:
- 判断栈是否已满:
- 向栈中压入元素:
- 从栈中弹出元素:
- 查看栈顶元素:
- 重写toString方法:
- 栈的基本代码汇总:
- 栈实现字符串中缀表达式运算:
- 栈实现字符串中缀表达式运算的要点:
- 栈实现前缀表达式计算
- 栈实现后缀表达式计算(个位运算)
- 栈实现后缀表达式的计算(多位数运算)
- 栈实现中缀表达式到后缀表达式的转化,并实现计算
- 中缀表达式转化位后缀表达式的要点:
栈
判断栈是否为空:
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();
}
}
}
}
栈实现字符串中缀表达式运算:
栈实现字符串中缀表达式运算的要点:
- 如果发现读入的字符内容是数值,直接存储到数字栈中
- 如果读入的字符是一个符号
- 如果符号栈中没有任何内容,那么直接存入到符号栈中
- 如果符号栈中已经有运算符,那么当前的字符和符号栈中的栈顶字符进行比较,若当前的运算符小于栈中的运算符,则需要从数字栈中弹出两个数值,再从符号栈中弹出一个运算符进行算术计算得到结果,并将结果保存在数字栈中,然后将当前的运算符推入符号栈
- 如果当前的符号运算的优先级大于等于符号栈中已有的运算符,那么当前的符号入栈
- 当表达式字符串整体扫描完成,就顺序的从数字栈和符号栈中弹出相应的数字和运算符,进行计算,并将结果存入数字栈,(当符号栈为空时,停止计算)
- 最后的结果存放在数字栈中;
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);
}
}
栈实现中缀表达式到后缀表达式的转化,并实现计算
中缀表达式转化位后缀表达式的要点:
- 首先要创建两个栈。
- a :一个栈用于储存字符串。记为S1
- b:一个栈用于存储雷士的计算结果,记为S2(实际用ArrayList代替更好)
- 从左向右遍历中缀表达式
- a:遇到操作数直接压入S2栈
- b:遇到运算符的时候比较其和S1栈顶运算符的优先级
- 如果S1栈为空,或栈顶运算符为左括号,则直接将此运算符入栈S1。
- 如果当前运算符的优先级高于栈顶运算符,也将当前运算符入栈S1。
- 否则将S1栈顶的运算符弹出并压入栈S2中,再次转到过程2,和新的栈顶运算符比较
- 遇到括号时
- a:如果是左括号,则直接压入S1
- b:如果是右括号,则依次弹出S1的栈顶运算符,直到遇到左括号为止,此时将这一对括号丢弃。
- 重复过程2和过程3,直到遍历完成中缀表达式list
- 将栈S1中剩余的运算符依次弹出并压入S2栈。
- 依次弹出栈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