栈实现综合计算器
最近在学习数据结构与算法的时候碰到了一个问题用栈实现综合计算器,发现网上还没有一个相对好理解的版本,所以有了这篇文章。
思路
数字直接压数栈
符号分情况,如果符号栈内无元素,直接压栈
如果有元素啧对比,如果当前符号优先级大于栈内所有元素,那么直接压栈
如果小于或等于,那么先运算栈内符号,这里有坑,要注意,用while来代替if(因为不止有一个需要判断)
//先来一个栈的接口
public interface Stack<T> {
T pop();
void push(T t);
T peek();
}
//定义节点
public class Node<T>{
T value;
Node<T> left;
Node<T> right;
public Node() {
}
public Node(T value) {
this.value = value;
}
public Node(T value, Node<T> left, Node<T> right) {
this.value = value;
this.left = left;
this.right = right;
}
}
//用双向链表来实现一个栈
public class LinkedStackDemo<T> implements Stack<T>{
private Node<T> first;
@Override
public T pop() {
if(first == null){
throw new NullPointerException("栈顶无元素!!");
}
Node<T> temp = first;
if(first.right != null){
first.right.left = null;
}
first = first.right;
return temp.value;
}
@Override
public void push(T t) {
Node add = new Node(t);
if(first == null){
first = add;
return;
}
add.right = first;
first.left = add;
first = add;
}
@Override
public T peek() {
if(first == null){
return null;
}
Node<T> temp = first;
return temp.value;
}
}
//计算器的实现
public class Calculator {
private static final List<Character> SYMBOL = Arrays.asList('+', '-', '*', '/');
private static final List<Character> SYMBOL2 = Arrays.asList('(', ')');
private static final Map<Character, Integer> LEVEL = new HashMap<Character, Integer>() {{
put('(', 1);
put('+', 8);
put('-', 9);
put('*', 10);
put('/', 11);
}};
//思路
//数字直接压数栈
//符号分情况,如果符号栈内无元素,直接压栈
//如果有元素啧对比,如果当前符号优先级大于栈内所有元素,那么直接压栈
//如果小于或等于,那么先运算栈内符号,这里有坑,要注意,用while来代替if(因为不止有一个需要判断)
public BigDecimal exec(String expression) {
char[] chars = expression.toCharArray();
Stack<BigDecimal> numStack = new LinkedStackDemo<>();
Stack<Character> symbolStack = new LinkedStackDemo<>();
StringBuffer numTemp = new StringBuffer();
for (char aChar : chars) {
if (SYMBOL.contains(aChar)) {
this.numberFormat(numStack, numTemp);
if (symbolStack.peek() == null) {
symbolStack.push(aChar);
} else {
while (symbolStack.peek() != null && LEVEL.get(aChar) <= LEVEL.get(symbolStack.peek())){
this.jisuan2(numStack, symbolStack);
}
symbolStack.push(aChar);
}
} else if (SYMBOL2.contains(aChar)) {
this.numberFormat(numStack, numTemp);
if (aChar == ')') {
while (symbolStack.peek() != '(') {
this.jisuan2(numStack, symbolStack);
}
symbolStack.pop();
} else {
symbolStack.push(aChar);
}
} else {
numTemp.append(aChar);
}
}
this.numberFormat(numStack, numTemp);
while (symbolStack.peek() != null) {
this.jisuan2(numStack, symbolStack);
}
return numStack.pop();
}
private void numberFormat(Stack<BigDecimal> numStack, StringBuffer numTemp) {
if (numTemp.length() != 0) {
BigDecimal bigDecimal = new BigDecimal(numTemp.toString());
numStack.push(bigDecimal);
numTemp.delete(0, numTemp.length());
}
}
private void jisuan2(Stack<BigDecimal> numStack, Stack<Character> symbolStack) {
BigDecimal right = numStack.pop();
BigDecimal left = numStack.pop();
BigDecimal jisuan = jisuan(left, right, symbolStack.pop());
numStack.push(jisuan);
}
private BigDecimal jisuan(BigDecimal left, BigDecimal right, char symbol) {
switch (symbol) {
case '+': {
return left.add(right);
}
case '-': {
return left.subtract(right);
}
case '*': {
return left.multiply(right);
}
case '/': {
return left.divide(right);
}
default: {
throw new RuntimeException("无效的类型!");
}
}
}
}
//测试用例
public class Test {
public static void main(String[] args) {
Calculator calculator = new Calculator();
System.out.println(calculator.exec("7-6-1-8"));
}
}
//也可以用数组来实现一个栈
public class ArrayStackDemo<T> implements Stack<T> {
private Object[] elements;
private int size;
private int max;
public ArrayStackDemo() {
this.elements = new Object[10];
this.max = 10;
}
@Override
public T pop() {
if(size == 0){
throw new NullPointerException("栈内无元素!");
}
return (T)elements[--size];
}
@Override
public void push(T t) {
if(size >= max){
max = max * 2;
Object[] objects = new Object[max];
System.arraycopy(elements, 0, objects, 0, size);
elements = objects;
}
elements[size++] = t;
}
@Override
public T peek() {
if(size == 0){
return null;
}
return (T)elements[size - 1];
}
}