Calculating polynomial implemented with a stack (java language)

  • The basic idea:

(1) by an index value as an index (int type) , to traverse polynomial;

(2) if a scanned digital , it directly into the operand stack ;

(3) if the scan to a symbol , on the following points:

a, if the current symbol stack is empty , directly to the symbol into the symbol stack ;

b, if the symbol stack is not empty , it must be a priority of comparison:

    1, if the current scan to operator precedence is less than or equal to the operator of the stack , it is necessary from  the operand stack of  pop  out of two numbers , while the symbol stack, the pop out of a symbol , the formula for computing configuration operation . The obtained calculation result into the operand stack , then the current scan to the operator the symbol stack

    2, if the current scan to the operator priority is greater than the top of the stack operator , directly into the symbol stack .

(4) When the polynomial when scanned , it sequentially from the operand stack and the symbol stack in pop the corresponding numbers and symbols ( each a pop out of 2 and a number of symbols , composed of a calculation formula for calculating the result of the operation pressure the number of stack ), ad infinitum.

(5) Finally, the symbol stack will be empty, the number of the last leaving the stack number , the number is the calculation result .


First create an array stack to achieve the basic operation is as follows:

// 定义一个ArrayStack 表示栈
class ArrayStackCul {
	private int maxSize; // 栈的最大容量
	private int[] stack; // 数组模拟栈,数据放在该数组中
	private int top = -1;//栈顶指针

	// 构造器
	public ArrayStackCul(int maxSize) {
		this.maxSize = maxSize;
		stack = new int[this.maxSize];
	}

	// 判断栈满
	public boolean isFull() {
		return top == maxSize - 1;
	}

	// 判断栈空
	public boolean isEmpty() {
		return top == -1;
	}

	// 入栈
	public void push(int value) {
		// 入栈前先判断栈是否满
		if (isFull()) {
			System.out.println("栈满!");
			return;
		}
		top++;
		stack[top] = value;
	}

	// 出栈
	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]);
		}
	}
}

In order to achieve polynomial arithmetic, but also to expand for the stack functions:

(1) In order to compare the scan strings for a current scan operators and stack operator  precedence, defined peek () method , direct return  element value of the stack , but not removed;

(2) comparison of priority premise is defined and return the priority , so the definition of priority (char oper) method , for return oper operator precedence;

(3) Since both polynomials operators have numbers, for convenience of distinction, defined isOper (char) method for determining whether the symbol is an operator ;

(4) defines a cal (int num1, int num2, char oper) method , depending on the oper operators, to achieve a different calculation formula unified computing .

	// 为了实现运算器的功能,需拓展功能:
	/*
	 * 返回运算符的优先级,优先级由程序员来确定,用数字来表示 默认:数字越大,优先级越高
	 */
  
  	/*
	 * 为了将扫描串中的运算符与栈顶运算符进行比较 定义一个方法,直接返回栈顶的元素值,但不取出
	 */
    //该方法用于查看栈顶元素
	public int peek() {
		return stack[top];
	}
  
    // 该方法用于返回元素的优先级
	// 在java中int 和 char 是可以比较的
	public int priority(int oper) {
		if (oper == '*' || oper == '/') {
			return 1;
		} else if (oper == '+' || oper == '-') {
			return 0;
		} else {
			return -1; // 以上定义是假设目前表达式只有+ - * / 四种运算
		}
	}

	// 判断当前扫描的符号是不是一个运算符
	// 本方法的目的是方便直接区分“运算符”与“数字”
	public boolean isOper(char val) {
		return val == '+' || val == '-' || val == '*' || val == '/';
	}// 在当前情景下,不是运算符当然就只能是数字了


    //此方法用于计算出栈元素构成运算式的运算结果
	// num1比num2先出栈,oper为运算符
	public int cal(int num1, int num2, int oper) {
		int res = 0;// res用来存放运算的结果
		switch (oper) {
		case '+':
			res = num2 + num1;
			break;
		case '-':
			res = num2 - num1;
			break;
		case '*':
			res = num2 * num1;
			break;
		case '/':
			res = num2 / num1;
			break;
		default:
			System.out.println("符号有误。");
			break;
		}
		return res;
	}

Finally beginning to realize the main function of the difficulty thinking :() Comment Details

package Stack;

public class Calculator {
	public static void main(String[] args) {
		// 根据前面的思路,完成表达式的运算
		String expression = "70+20*6-20/4"; // 如何处理多位数的问题?
		// 创建两个栈,一个数栈,一个符号栈
		ArrayStackCul numStack = new ArrayStackCul(10);
		ArrayStackCul operStack = new ArrayStackCul(10);
		// 创建需要的变量
		int index = 0;// 用于扫描
		char ch = ' ';// 扫描到的结果存储在ch里面,进行下一步的判断

		int num1;
		int num2;
		int oper;// num1为先出栈数据
		int res;// 运算结果

		String keepNum = "";// 用于处理多位数运算问题(难点),该变量用来存储一个多位数
		while (true) {
			// 开始扫描
			ch = expression.substring(index, index + 1).charAt(0);
			// subString指的是取一个子串;charAt(0)表示取子串的第一个字符
			if (operStack.isOper(ch)) {// 如果是运算符
				if (!operStack.isEmpty()) {
					if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
						// ① 扫描的当前运算符 < 栈顶运算符 ——> 执行思路1
						num1 = numStack.pop();
						num2 = numStack.pop();
						oper = operStack.pop();
						res = numStack.cal(num1, num2, oper);
						// 运算出的结果入栈
						numStack.push(res);
						// 最后还要将当前优先级小的运算符入栈
						operStack.push(ch);
					} else {
						// ② 当前运算符的优先级大,执行思路2
						operStack.push(ch);
					}
				} else {// 如果当前符号栈为空,则直接入栈
					operStack.push(ch);
				}
			} else {// 如果是数字,直接入数字栈
				/*
				 * // numStack.push(ch);//这样写是错误的,因为我们得到的数字其实是'字符'
				 * numStack.push(ch - 48);//字符模式的数 与 数字模式的数 ASCII码差了48
				 */
				// 以上做法无法处理多位数的问题,解决多位数计算问题的思路:
				/*
				 * 1、当处理数时,不能发现是一个数,就直接入栈 2、在处理数字时,需要想expression的表达式的index后再看一位
				 * 如果是数,就继续扫描;如果是运算符,则将扫描的整体转换成数值后入栈
				 * 3、因此需要定义一个字符串变量用于拼接(KeepNum)
				 */
				keepNum += ch;
				// 往后试探一位index + 1 ,如果是数字,则继续扫描;如果是运算符,则入栈
				// 另外如果ch已经是expression的最后一位,就直接入栈
				if (index == expression.length() - 1) {
					numStack.push(Integer.parseInt(keepNum));
                    //必须将多位数转换成一个整型数,才能参与运算
				} else {
					//如果没有上面这个判断,会报越界错误。
					//这启发我们:对最后一位一定要慎重考虑,优化逻辑
					if (operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))) {
						numStack.push(Integer.parseInt(keepNum));
						// 十分重要!!!:必须将keepNum置为空
						keepNum = "";
					}
				}

			}

			// 让index + 1 , 并判断是否扫描到expression的最后
			// index只是扫描的索引,每扫描一个字符就+1,index >= 字符串长度时,表示扫描完
			index++;
			if (index >= expression.length()) {
				break;
			}
		}

		// 表达式扫描完毕后,
		// 依次弹出两个栈中的数和符号,依次计算结果,直到符号栈空
		while (true) {
			// ③ 如果符号栈为空,则计算最后的结果,即数栈中的最后一个数
			if (operStack.isEmpty()) {
				break;
			}
			num1 = numStack.pop();
			num2 = numStack.pop();
			oper = operStack.pop();
			res = numStack.cal(num1, num2, oper);
			numStack.push(res);
		}
		// 将数栈中最后一个数pop出来,就是结果
		int result = numStack.pop();
		System.out.printf("表达式%s = %d", expression, result);

	}

}
}

 

Released seven original articles · won praise 1 · views 893

Guess you like

Origin blog.csdn.net/weixin_40389106/article/details/104071631