原文地址:傳送門
使用棧來完成一個表達式的結果
使用棧完成計算 一個表達式的結果
7*2*2-5+1-5+3-4 = ?
3+2*6-2
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XzPnJzRe-1614845779689)(https://victorfengming.gitee.io/data_algorithm/img/QQ%E6%88%AA%E5%9B%BE20210220134231.png)]
使用棧完成表達式的計算 思路
- 通過一個 index 值(索引),來遍歷我們的表達式
- 如果我們發現是一個數字, 就直接入數棧
- 如果發現掃描到是一個符號, 就分如下情況
- 3.1 如果發現當前的符號棧為 空,就直接入棧
- 3.2 如果符號棧有操作符,就進行比較,如果當前的操作符的優先級小于或者等于棧中的操作符 就需要從數棧中pop出兩個數,在從符號棧中pop出一個符號,進行運算,將得到結果,入數棧,然后將當前的操作符入符號棧, 如果當前的操作符的優先級大于棧中的操作符, 就直接入符號棧.
- 當表達式掃描完畢,就順序的從 數棧和符號棧中pop出相應的數和符號,并運行.
- 最后在數棧只有一個數字,就是表達式的結果
驗證: 3+2*6-2 = 13
一位數運算
計算
package com.atguigu.stack;/*** ClassName: <br/>* Description: <br/>* Date: 2021-02-20 14:02 <br/>* @project data_algorithm* @package com.atguigu.stack*/
public class Calculator {}//先創建一個棧,直接使用前面創建好
//定義一個 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];}//增加一個方法,可以返回當前棧頂的值, 但是不是真正的poppublic int peek() {return stack[top];}//棧滿public boolean isFull() {return top == maxSize - 1;}//棧空public boolean isEmpty() {return top == -1;}//入棧-pushpublic 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]);}}//返回運算符的優先級,優先級是程序員來確定, 優先級使用數字表示//數字越大,則優先級就越高.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 == '/';}//計算方法public int cal(int num1, int num2, int oper) {int res = 0; // res 用于存放計算的結果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;}}
啟動
public static void main(String[] args) {//根據前面老師思路,完成表達式的運算String expression = "7*2*2-5+1-5+3-4"; // 15//如何處理多位數的問題?//創建兩個棧,數棧,一個符號棧ArrayStack2 numStack = new ArrayStack2(10);ArrayStack2 operStack = new ArrayStack2(10);//定義需要的相關變量int index = 0;//用于掃描int num1 = 0; int num2 = 0;int oper = 0;int res = 0;char ch = ' '; //將每次掃描得到char保存到chString keepNum = ""; //用于拼接 多位數//開始while循環的掃描expressionwhile(true) {//依次得到expression 的每一個字符ch = expression.substring(index, index+1).charAt(0);//判斷ch是什么,然后做相應的處理if(operStack.isOper(ch)) {//如果是運算符//判斷當前的符號棧是否為空if(!operStack.isEmpty()) {//如果符號棧有操作符,就進行比較,如果當前的操作符的優先級小于或者等于棧中的操作符,就需要從數棧中pop出兩個數,//在從符號棧中pop出一個符號,進行運算,將得到結果,入數棧,然后將當前的操作符入符號棧if(operStack.priority(ch) <= operStack.priority(operStack.peek())) {num1 = numStack.pop();num2 = numStack.pop();oper = operStack.pop();res = numStack.cal(num1, num2, oper);//把運算的結果如數棧numStack.push(res);//然后將當前的操作符入符號棧operStack.push(ch);} else {//如果當前的操作符的優先級大于棧中的操作符, 就直接入符號棧.operStack.push(ch);}}else {//如果為空直接入符號棧..operStack.push(ch); // 1 + 3}} else { //如果是數,則直接入數棧//numStack.push(ch - 48); //? "1+3" '1' => 1//分析思路//1. 當處理多位數時,不能發現是一個數就立即入棧,因為他可能是多位數//2. 在處理數,需要向expression的表達式的index 后再看一位,如果是數就進行掃描,如果是符號才入棧//3. 因此我們需要定義一個變量 字符串,用于拼接//處理多位數keepNum += ch;//如果ch已經是expression的最后一位,就直接入棧if (index == expression.length() - 1) {numStack.push(Integer.parseInt(keepNum));}else{//判斷下一個字符是不是數字,如果是數字,就繼續掃描,如果是運算符,則入棧//注意是看后一位,不是index++if (operStack.isOper(expression.substring(index+1,index+2).charAt(0))) {//如果后一位是運算符,則入棧 keepNum = "1" 或者 "123"numStack.push(Integer.parseInt(keepNum));//重要的!!!!!!, keepNum清空keepNum = "";}}}//讓index + 1, 并判斷是否掃描到expression最后.index++;if (index >= expression.length()) {break;}}//當表達式掃描完畢,就順序的從 數棧和符號棧中pop出相應的數和符號,并運行.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 res2 = numStack.pop();System.out.printf("表達式 %s = %d", expression, res2);}
原文地址:傳送門