Java数据结构与算法-栈实现综合计算器(中缀表达式)

栈实现综合计算器(中缀表达式)

栈的学习目标

1. 栈的介绍以及特点
2. 栈的应用
3. 代码实现案例
4. 分析案例难点

一,栈的介绍以及特点
栈是一个特殊的线性表,限定只能在尾部(栈顶)进行插入和删除,可以用数组模拟也可以用链表模拟,特点是先进后出,第一个入栈的元素放到了栈底,第一个出去的元素称为栈顶。

二,栈的应用场景
比如逆序打印队列或者链表都可以利用栈的特点实现,这次我的案例是计算一个表达式的值,利用栈进行存储数据。

三,代码实现
计算:2*30/5-2的值

package com.atxiaopeng.stack;

public class StackDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//计算3*3+5-2
		Stack numStack = new Stack(10);//数字栈
		Stack opersStack = new Stack(10);//符号栈
		
		int index = 0;
		int num1= 0;
		int num2 = 0;
		int oper = 0;//运算符
		String keep = "";//组合新的字符串
		String string = "2*30/5-2";//要计算的表达式,最后取的是整型,不考虑浮点数
		
		while (index < string.length()) {
			char ch = string.substring(index, index+1).charAt(0);//截取单个字符,注意这是前开后闭截取字符串
			if (ch>='0'&& ch<='9') {
				keep = keep +ch;//重新组合字符串,就是为了解决多位数的运算
				if (index == string.length()-1) {
					numStack.pushStack(Integer.parseInt(keep));
				} else {
					//判断是否下个字符为运算符,假如就可以进栈了
					if(opersStack.isOper(string.substring(index+1,index+2).charAt(0))) {
						numStack.pushStack(Integer.parseInt(keep));
						keep = "";
					}
				}
				
			}else if (opersStack.isOper(ch)) {
				if (opersStack.isEmpty()) {
					opersStack.pushStack(ch);
				}else {
					//假如当前运算符的级别低于栈顶的运算级别,这时候就从数字栈中取出来两个数字,把符号栈中的栈顶元素取出运算
					if (opersStack.priority(ch) <= opersStack.priority(opersStack.peek())) {
						num1 = numStack.pop();
						num2 = numStack.pop();
						oper = opersStack.pop();
						numStack.pushStack(opersStack.cal(num1, num2, oper));
						opersStack.pushStack(ch);//然后再把当前运算符号进占
					}else {
						opersStack.pushStack(ch);
					}
					
				}
			}else {
				System.out.println("表达式内部存在错误字符!");
				return;
			}
			
			index++;
			
		}
		//然后就依次取出运算既可以
		while (true) {
			if (opersStack.isEmpty()) {
				break;
			}
			num1 = numStack.pop();
			num2 = numStack.pop();
			oper = opersStack.pop();
			numStack.pushStack(opersStack.cal(num1, num2, oper));
			
		}
		System.out.println(numStack.pop());
		
		numStack.showStack();
		opersStack.showStack();
		
	}

}

class Stack{
	
	int top = -1;
	int maxsize ;
	int stackarr[];
    public Stack(int max) {
    	this.maxsize = max;
    	stackarr = new int[max];
	}
    
    public boolean isEmpty () {
		return top == -1;
	}

    public boolean isFull() {
    	return top == maxsize-1;
	}
    
    public void pushStack(int a) {
		if (isFull()) {
			System.out.println("栈已经满了!");
			return;
		}
		top++;
		stackarr[top] = a;
	}
    //查看栈顶元素,并不是出栈
    public int  peek() {
		return stackarr[top];
	}
    
    public int  pop() {
		if (isEmpty()) {
			return 0;
		}
		
		return stackarr[top--];
	}
    
    public void showStack() {
		if (isEmpty()) {
			System.out.println("栈为空!");
			return;
		}
		for (int i = top; i >= 0; i--) {
			System.out.printf("栈内的元素有:%d \n", stackarr[i]);
		}
	}
    //比较优先级
    public int  priority(int oper) {
		if (oper == '*'||oper =='/') {
			return 1;
		}else if (oper =='+'||oper == '-') {
			return 0;
		}else {
			return -1;
		}
		
	}
    //判断是否为运算符号
    public boolean isOper(char ch) {
		return ch == '+'||ch =='-'||ch =='*'||ch =='/';
	}
    
    //计算方法
    
    public int  cal(int num1,int num2,int oper) {
		int res = 0;
		switch (oper) {
		case '+': res =num1+num2;
			
			break;
		case '-': res =num2-num1;
		
		break;
		case '*': res =num1*num2;
		
		break;
		case '/': res =num2/num1;
		
		break;
		default:
			break;
		}
		return res;
    	
	}
    
	
}

四,代码难点分析

  1. 搞清楚运算的优先级别,先计算谁后计算谁,整个代码的核心就是先计算谁和谁,不然结果就会出现错误。
  2. 而且要考虑到多位数运算的情况。思路就是你用一个string接收每次读取的字符,判断下一位是符号还是数字,如果是数字就接着给string,如果是字符string就可以入栈了,注意要判断一下,不要让数组下标越界。
  3. 如果操作符号的优先级别小于(优先级别自己可以设置)如果当前优先级别小于或等于符号栈中的栈顶元素的优先级,则从数栈中取出两个数,并把符号栈的栈顶元素取出进行计算,结果入数栈,并且当前操作符入符号栈。
  4. 而且操作数不要搞反了。。。。

共同学习,一起进步!

你可能感兴趣的:(算法,数据结构,java,栈,队列)