什么是栈?
简单讲就是先进后出,吃进去吐出来,可以用链表实现,也可以用数组实现
我们来看看jdk1.8中栈的源码
public
class Stack<E> extends Vector<E> {
/**
* Creates an empty Stack.
*/
public Stack() {
}
public E push(E item) {
addElement(item);
return item;
}
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
public boolean empty() {
return size() == 0;
}
public synchronized int search(Object o) {
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = 1224463164541339165L;
}
可以看出,它是继承Vertor,并且封装了自己特有的的几个方法
自定义栈实现中缀表达式计算
一共包含四个类,第一个是栈的操作,第二第三个是和操作相关
大概的算法思想
0.创建数字栈和符号栈
1.创建index用来循环扫描expression
2.如果E[index]是数字,直接入数栈
3.若E[index]是符号,
1)如果当前的符号栈为空,入符号栈
2)如果当前符号栈不为空,进行比较
1)如果当前操作符优先级《=OperStack栈顶的操作符
就从numStack中pop两个数,从符号栈中pop一个operator,进行运算,将运算结果进numStack,再把当前operator进operStack。
2)如果 > operStack[top],直接入operStack.
4.如果栈中最后只有一个数字,那就是结果
ArrayStack .java 包含了栈的相关操作
/**
* @author Administrator
* @date 2019/6/14/14:05
*/
public class ArrayStack {
/**
* 栈的最大容量
*/
private int maxSize;
/**
* 用数组模拟栈
*/
private int[] stack;
/**
* 栈顶指针,初始位置为-1
*/
int top = -1;
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
stack = new int[maxSize];
}
/**
* 判断是否栈满
* @return 满/true否则false
*/
public boolean isFull(){
return top == maxSize-1;
}
/**
* 判断是否栈空
* @return 空/true否则false
*/
public boolean isEmpty(){
return top == -1;
}
/**
* 入栈
* 栈顶指针+1
* @param Node
*/
public void push(int Node){
//判断是否栈满,满了则不能入栈
if (isFull()){
System.out.println("栈满");
return;
}
//入栈操作
top++ ;
stack[top] = Node;
}
/**
* 出栈
* 栈顶指针减1
* @return
*/
public synchronized int pop(){
//定义返回的数据
int obj;
//判断是否栈空
if (isEmpty()){
System.out.println("栈空");
throw new RuntimeException("栈空!");
}
//出栈操作
obj = stack[top];
top--;
return obj;
}
/**
* 显示栈里的数据
*/
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]);
}
}
public int peek() {
return stack[top];
}
}
NumStack.java 数字栈继承ArrayStack
/**
* 数字栈
* 继承ArrayStack
* 1 计算结果
* @author Administrator
* @date 2019/6/14/14:06
*/
public class NumStack<T extends Integer> extends ArrayStack{
//
public NumStack(int maxSize) {
super(maxSize);
}
/**
* 计算每一次弹出的运算结果
* @param num1 先弹出的数字
* @param num2 后弹出的数字
* @param operator 运算符
*/
public int calculate(int num1 , int num2 , int operator){
//返回的计算结果
int res = 0;
//根据操作符类型进行运算
switch (operator){
case '+':
res = num1 + num2;
break;
case '*':
res = num1 * num2;
break;
case '/':
res = num2 / num1;
break;
case '-':
res = num2 - num1;
break;
default:
break;
}
return res;
}
}
OperStack.java 符号栈继承 ArrayStack
/**
* 运算符栈
* @author Administrator
* @date 2019/6/14/14:06
*/
public class OperStack<T extends Integer> extends ArrayStack {
//必须实现父类的有参构造
public OperStack(int maxSize) {
super(maxSize);
}
/**
* 判断是否是运算符
* @param oper
* @return 是/true
*/
public boolean isOper(char oper){
return oper=='+' || oper=='-' || oper=='*' ||oper=='/';
}
/**
* 判断运算符优先级,数字大的优先级高
* @param operator
* @return
*/
public int priority(int operator){
if (operator=='*' || operator=='/'){
return 1;
}
else if (operator=='+' || operator=='-'){
return 0;
}
else {
return -1;
}
}
}
CalculatorDemo .java 计算中缀表达式(主方法)
/**
* 计算中缀表达式
* @author Administrator
* @date 2019/6/14/14:36
*/
public class CalculatorDemo {
/**
* 符号栈
*/
public static OperStack<Integer> operStack = new OperStack(10);
/**
* 数字栈
*/
public static NumStack<Integer> numStack = new NumStack<>(10);
/**
* 主方法
* @param args
*/
public static void main(String[] args) {
//需要计算的表达式,仅限整数
String expression = "5+8*40/10";
//表示当前的扫描的字符
char ch ;
//当前字符的下标
int index = 0;
//用于数字拼接
String nums = "";
//循环扫描expression
while (true){
//当前的字符
ch = expression.substring(index,index+1).charAt(0);
//如果是运算符
if (operStack.isOper(ch)){
//1)如果当前的符号栈为空,入符号栈果
if (operStack.isEmpty()){
operStack.push(ch);
}
//2)如果当前符号栈不为空,进行比较
else {
//1)如果当前操作符优先级《=OperStack栈顶的操作符
//就从numStack中pop两个数,从符号栈中pop一个operator,进行运算,将运算结果进numStack,再把当前operator进operStack。
if (operStack.priority(ch) <= operStack.priority(operStack.peek())){
int num1 = numStack.pop();
int num2 = numStack.pop();
int tempOper = operStack.pop();
int res = numStack.calculate(num1,num2,tempOper);
numStack.push(res);
operStack.push(ch);
}
// 2)如果 > operStack[top],直接入operStack.
else{
operStack.push(ch);
}
}
}
//是数字,数字入数栈
else {
//多位数的数字我们不能直接进栈,而是需要字符串拼接
nums +=ch;
//index已经是最后一位了,直接入栈
if (index == expression.length()-1){
numStack.push(Integer.parseInt(nums));
}
else {
//如果下一个是运算符,才push
if (operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
//进栈
numStack.push(Integer.parseInt(nums));
//!!!置空,重要
nums = "";
}
}
}
//要再前面,否者会由数组下标越界异常
index ++;
//当扫描到最后一个字符的后一个时结束循环
if (index >= expression.length()){
break;
}
}//while
//当表达式扫描完毕
while (true){
if (operStack.isEmpty()){
break;
}
int num1 = numStack.pop();
int num2 = numStack.pop();
int tempOper = operStack.pop();
int res = numStack.calculate(num1,num2,tempOper);
numStack.push(res);
}
//将最后结果出栈
int result = numStack.pop();
System.out.printf("表达式:%s = %d",expression,result);
}//main
}