package stack;
/**
* @author taoke
* @desc 利用栈实现计算器
* @email 1504806660@qq.com
* @date 2021/12/30
*/
public class Calulator {
/**
* 计算器
* 思路:
* 1、挨个遍历字符,如果是数字,判断后面一位是否是数字
* 1.1 如果还是数字,继续遍历后面一个字符,并且用keepNum保存起来
* 1.2 如果是字符,把keepNum放入数栈,清空keepNum
* 2、如果当前是字符
* 2.1 如果符号栈为空,直接入栈
* 2.2 如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈的操作符,就需要pop出两个数,符号栈中pop出
* 一个数,计算出结果,将结果入数栈,将当前的符号入符号栈。
* 如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈。
* 3、表达式遍历完毕,顺序从数栈和符号栈中pop出相应的数和符号,计算结果
* 4、当符号栈为空时,数栈只剩下一个数字,就是计算结果
*
* @param args 参数
*/
public static void main(String[] args) {
String expression = "1-2*6-20";
Stack numStack = new Stack(10);
Stack charStack = new Stack(10);
char[] chars = expression.toCharArray();
StringBuilder keepNum = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (charStack.isCharacter(chars[i])) {
if (!charStack.isEmpty()) {
if (charStack.priority(chars[i]) <= charStack.priority(charStack.peek())) {
int num1 = numStack.pop();
int num2 = numStack.pop();
int ch = charStack.pop();
int result = charStack.calculate(num1, num2, ch);
numStack.push(result);
}
}
charStack.push(chars[i]);
} else {
keepNum.append(chars[i]);
if (i < chars.length - 1) {
if (numStack.isCharacter(chars[i + 1])) {
numStack.push(Integer.parseInt(keepNum.toString()));
keepNum = new StringBuilder();
}
} else {
if (!"".equals(keepNum.toString())) {
numStack.push(Integer.parseInt(keepNum.toString()));
} else {
numStack.push(chars[i]);
}
}
}
}
while (!charStack.isEmpty()) {
int num1 = numStack.pop();
int num2 = numStack.pop();
int ch = charStack.pop();
int result = charStack.calculate(num1, num2, ch);
numStack.push(result);
}
System.out.printf(" %s = %d \n", expression, numStack.pop());
}
static class Stack {
/**
* 栈顶位置
*/
private int top;
/**
* 栈的最大容量
*/
private final int maxSize;
/**
* 实际存放的数据
*/
private final int[] data;
public Stack(int maxSize) {
this.maxSize = maxSize;
this.data = new int[maxSize];
top = -1;
}
/**
* 判断栈是否已经满了
*
* @return 是否已经满了
*/
public boolean isFull() {
return top == maxSize - 1;
}
/**
* 判断栈是否为空
*
* @return 栈是否为空
*/
public boolean isEmpty() {
return top == -1;
}
/**
* 入栈
*
* @param num 待添加数据
*/
public void push(int num) {
if (isFull()) {
System.out.println("栈已经满了~");
return;
}
top++;
data[top] = num;
}
/**
* 出栈
*/
public int pop() {
if (isEmpty()) {
System.out.println("栈为空~");
return -1;
}
int result = data[top];
data[top] = 0;
top--;
return result;
}
/**
* 返回栈顶数据,但是不出栈
*
* @return 栈顶数据
*/
public int peek() {
if (isEmpty()) {
System.out.println("栈为空~");
return -1;
}
return data[top];
}
/**
* 打印栈存放的数据
*/
public void show() {
if (isEmpty()) {
System.out.println("栈为空~");
return;
}
for (int i = 0; i <= top; i++) {
System.out.printf("栈存放的数据 %d \n", data[i]);
}
}
/**
* 获取字符的优先级
*
* @param ch 字符
* @return 优先级
*/
public int priority(int ch) {
if (ch == '*' || ch == '/') {
return 1;
} else if (ch == '+' || ch == '-') {
return 0;
} else {
return -1;
}
}
/**
* 计算两数的值
*
* @param num1 数字一
* @param num2 数字二
* @param ch 计算符
* @return 结果
*/
public int calculate(int num1, int num2, int ch) {
int result = 0;
switch (ch) {
case '+':
result = num1 + num2;
break;
case '-':
result = num2 - num1;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num2 / num1;
break;
}
return result;
}
/**
* 判断是否为符号
*
* @param ch 带判断字符
* @return 是否为符号
*/
public boolean isCharacter(char ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
public boolean isNumber(char ch) {
return ch >= 48 && ch <= 57;
}
}
}
数据结构与算法-栈-计算器(中缀表达式)
于 2021-12-31 09:50:00 首次发布