##栈实现计算器
package com.atguigu.stack;
public class Calculator {
public static void main(String[] args) {
{
//执行顺序 1.压入3在数值栈 2.压入+在符号栈 3.压入6在数字栈 4.当前栈中的优先级小于即将压入的,符号栈中压入*
String express="3+6*2";
//定义符号栈
ArrayStack2 oprStack = new ArrayStack2(10);
//定义数值栈
ArrayStack2 numStack = new ArrayStack2(20);
//定义所需要的变量
int index=0;
int num1=0;
int num2=0;
int result=0;
int opr=0;
//扫描表达式
while(true)
{
char c=express.substring(index,index+1).charAt(0);
if(oprStack.isOper(c))
{
//说明是运算符,看栈是否为空
if(oprStack.isEmpty())
{
//直接压入
oprStack.push(c);
}
else
{
//比较优先级,如果当前的字符优先级小于或者等于栈中的运算符就把栈中的运算符弹出来
if(oprStack.priority(c)<=oprStack.priority(oprStack.pick()))
{
//弹出运算符,并弹出两个数进行计算,在此之前肯定有数压入了
num1=numStack.pop();
num2=numStack.pop();
opr=oprStack.pop();
result=oprStack.cum(num1,num2,opr);
numStack.push(result);
}
else
{
//如果优先级大于栈中的符号,直接将符号压入
oprStack.push(c);
}
}
}
else
{
//说明是一个数
numStack.push(c-48);
}
index++;
if(index==express.length())
{
break;
}
}
//将数值栈与符号栈中的元素依次取出计算 此时数值栈中的元素有2 6 3 符号栈中的是* + 2*6 的结果压入数值栈再计算2*6的结果+3
while (true)
{
if(oprStack.isEmpty())
{
//说明计算完毕
break;
}
num1=numStack.pop();
num2=numStack.pop();
opr=oprStack.pop();
result=oprStack.cum(num1,num2,opr);
numStack.push(result);
}
System.out.printf("%s=%d",express,numStack.pop());
}
}
}
//先创建一个栈,直接使用前面创建好
//定义一个 ArrayStack2 表示栈, 需要扩展功能
class ArrayStack2 {
private int maxSize; // 栈的大小
private int[] stack; // 数组,数组模拟栈,数据就放在该数组
private int top = -1;// top表示栈顶,初始化为-1
//构造器
public ArrayStack2(int maxSize) {
this.maxSize = maxSize;
stack = new int[this.maxSize];
}
//栈满
public boolean isFull() {
return top == maxSize - 1;
}
//栈空
public boolean isEmpty() {
return top == -1;
}
//入栈-push
public void push(int value) {
//先判断栈是否满
if(isFull()) {
System.out.println("栈满");
return;
}
top++;
stack[top] = value;
}
//出栈pop
public int pop() {
//先判断栈是否空
if(isEmpty()) {
//抛出异常
throw new RuntimeException("栈空,没有数据~");
}
int value = stack[top];
top--;
return value;
}
//显示栈的情况[遍历栈], 遍历时,需要从栈顶开始显示数据
public void list() {
if (isEmpty()) {
System.out.println("栈空,没有数据~~");
return;
}
//需要从栈顶开始显示数据
for (int i = top; i >= 0; i--) {
System.out.printf("stack[%d]=%d\n", i, stack[i]);
}
}
/**
* 取得栈顶的值
* @return
*/
public int pick()
{
return stack[top];
}
//实现计算器的思路分析:定义两个栈一个是数值栈一个是符号栈
//当拿到表达式(字符串)时定义一个索引去遍历表达式
//如果是数值的话就放在数值栈,如果是符号的话就放在符号栈
//在放入运算符之前需要执行的操作:如果符号栈是空的直接放入,如果是非空需要比较运算符的优先级,如果栈中的优先级较高,则需要先取出运算符进行计算(结果压入数值栈),再将运算符压入栈中
/**
* 判断运算符号的优先级
* @param opr
* @return
*/
public int priority(int opr) {
if (opr == '+' || opr == '-') {
return 0;
} else if (opr == '*' || opr == '/') {
return 1;
} else {
return -1;
}
}
/**
* 判断是否是运算符(char与int是可以混用的)
* @param val
* @return
*/
public boolean isOper(char val)
{
return val=='+' || val=='-' || val=='*' || val=='/';
}
/**
* 数值运算的方法
* @param num1
* @param num2
* @param opr
* @return
*/
public int cum(int num1,int num2,int opr)
{
int result=0;
switch (opr)
{
case '+':
result=num1+num2;
break;
case '-':
result=num1-num2;
break;
case '*':
result=num1*num2;
break;
case '/':
result=num1/num2;
break;
}
return result;
}
}