java中應(yīng)用Stack進行算術(shù)運算的操作
java.util.stack,繼承自Vector
FILO, 適合帶有小括號的算術(shù)運算
import java.util.Stack;
/**
* 利用棧,進行四則運算的類
* 用兩個棧來實現(xiàn)算符優(yōu)先,一個棧用來保存需要計算的數(shù)據(jù)numStack,一個用來保存計算優(yōu)先符priStack
*
* 基本算法實現(xiàn)思路為:用當(dāng)前取得的運算符與priStack棧頂運算符比較優(yōu)先級:若高于,則因為會先運算,放入棧頂;
* 若等于,因為出現(xiàn)在后面,所以會后計算,所以棧頂元素出棧,取出操作數(shù)運算;
* 若小于,則同理,取出棧頂元素運算,將結(jié)果入操作數(shù)棧。各個優(yōu)先級'(' > '*' = '/' > '+' = '-' > ')'
*
*/
public class Operate {
private Stack<Character> priStack = new Stack<Character>();// 操作符棧
private Stack<Integer> numStack = new Stack<Integer>();;// 操作數(shù)棧
/**
* 傳入需要解析的字符串,返回計算結(jié)果(此處因為時間問題,省略合法性驗證)
* @param str 需要進行技術(shù)的表達式
* @return 計算結(jié)果
*/
public int caculate(String str) {
// 1.判斷string當(dāng)中有沒有非法字符
String temp;// 用來臨時存放讀取的字符
// 2.循環(huán)開始解析字符串,當(dāng)字符串解析完,且符號棧為空時,則計算完成
StringBuffer tempNum = new StringBuffer();// 用來臨時存放數(shù)字字符串(當(dāng)為多位數(shù)時)
StringBuffer string = new StringBuffer().append(str);// 用來保存,提高效率
while (string.length() != 0) {
temp = string.substring(0, 1);
string.delete(0, 1);
// 判斷temp,當(dāng)temp為操作符時
if (!isNum(temp)) {
// 1.此時的tempNum內(nèi)即為需要操作的數(shù),取出數(shù),壓棧,并且清空tempNum
if (!"".equals(tempNum.toString())) {
// 當(dāng)表達式的第一個符號為括號
int num = Integer.parseInt(tempNum.toString());
numStack.push(num);
tempNum.delete(0, tempNum.length());
}
// 用當(dāng)前取得的運算符與棧頂運算符比較優(yōu)先級:若高于,則因為會先運算,放入棧頂;若等于,因為出現(xiàn)在后面,所以會后計算,所以棧頂元素出棧,取出操作數(shù)運算;
// 若小于,則同理,取出棧頂元素運算,將結(jié)果入操作數(shù)棧。
// 判斷當(dāng)前運算符與棧頂元素優(yōu)先級,取出元素,進行計算(因為優(yōu)先級可能小于棧頂元素,還小于第二個元素等等,需要用循環(huán)判斷)
while (!compare(temp.charAt(0)) && (!priStack.empty())) {
int a = (int) numStack.pop();// 第二個運算數(shù)
int b = (int) numStack.pop();// 第一個運算數(shù)
char ope = priStack.pop();
int result = 0;// 運算結(jié)果
switch (ope) {
// 如果是加號或者減號,則
case '+':
result = b + a;
// 將操作結(jié)果放入操作數(shù)棧
numStack.push(result);
break;
case '-':
result = b - a;
// 將操作結(jié)果放入操作數(shù)棧
numStack.push(result);
break;
case '*':
result = b * a;
// 將操作結(jié)果放入操作數(shù)棧
numStack.push(result);
break;
case '/':
result = b / a;// 將操作結(jié)果放入操作數(shù)棧
numStack.push(result);
break;
}
}
// 判斷當(dāng)前運算符與棧頂元素優(yōu)先級, 如果高,或者低于平,計算完后,將當(dāng)前操作符號,放入操作符棧
if (temp.charAt(0) != '#') {
priStack.push(new Character(temp.charAt(0)));
if (temp.charAt(0) == ')') {// 當(dāng)棧頂為'(',而當(dāng)前元素為')'時,則是括號內(nèi)以算完,去掉括號
priStack.pop();
priStack.pop();
}
}
} else
// 當(dāng)為非操作符時(數(shù)字)
tempNum = tempNum.append(temp);// 將讀到的這一位數(shù)接到以讀出的數(shù)后(當(dāng)不是個位數(shù)的時候)
}
return numStack.pop();
}
/**
* 判斷傳入的字符是不是0-9的數(shù)字
*
* @param str
* 傳入的字符串
* @return
*/
private boolean isNum(String temp) {
return temp.matches("[0-9]");
}
/**
* 比較當(dāng)前操作符與棧頂元素操作符優(yōu)先級,如果比棧頂元素優(yōu)先級高,則返回true,否則返回false
*
* @param str 需要進行比較的字符
* @return 比較結(jié)果 true代表比棧頂元素優(yōu)先級高,false代表比棧頂元素優(yōu)先級低
*/
private boolean compare(char str) {
if (priStack.empty()) {
// 當(dāng)為空時,顯然 當(dāng)前優(yōu)先級最低,返回高
return true;
}
char last = (char) priStack.lastElement();
// 如果棧頂為'('顯然,優(yōu)先級最低,')'不可能為棧頂。
if (last == '(') {
return true;
}
switch (str) {
case '#':
return false;// 結(jié)束符
case '(':
// '('優(yōu)先級最高,顯然返回true
return true;
case ')':
// ')'優(yōu)先級最低,
return false;
case '*': {
// '*/'優(yōu)先級只比'+-'高
if (last == '+' || last == '-')
return true;
else
return false;
}
case '/': {
if (last == '+' || last == '-')
return true;
else
return false;
}
// '+-'為最低,一直返回false
case '+':
return false;
case '-':
return false;
}
return true;
}
public static void main(String args[]) {
Operate operate = new Operate();
int t = operate.caculate("(3+4*(4*10-10/2)#");
System.out.println(t);
}
}
補充:java stack實現(xiàn)的中綴簡單四則運算表達式計算
我就廢話不多說了,大家還是直接看代碼吧~
public abstract class Stack<T> {
public abstract boolean isEmpty();
public abstract boolean isFull();
public abstract T top();
public abstract boolean push(T x);
public abstract T pop();
public abstract void clear();
}
public class SeqStack<T> extends Stack<T> {
private Object[] elementData;
private int maxTop;
private int top;
public SeqStack(int size) {
this.maxTop = size - 1;
elementData = new Object[size];
top = -1;
}
@Override
public boolean isEmpty() {
return top == -1;
}
@Override
public boolean isFull() {
return top == maxTop - 1;
}
@SuppressWarnings("unchecked")
@Override
public T top() {
if (top == -1) {
System.out.println("Empty");
return null;
}
return (T) elementData[top];
}
@Override
public boolean push(T x) {
if (top == maxTop) {
System.err.println("Full");
return false;
}
elementData[++top] = x;
return true;
}
@SuppressWarnings("unchecked")
@Override
public T pop() {
if (top == -1) {
System.err.println("Empty");
return null;
}
T result = (T)elementData[top];
elementData[top] = null; //gc
top--;
return result;
}
@Override
public void clear() {
//let gc do its work
for(int i = 0; i < top+1; i++) {
elementData[i] = null;
}
top = -1;
}
}
public class StackCalc {
private SeqStack<Integer> stack;
public StackCalc(int maxSize) {
stack = new SeqStack<Integer>(maxSize);
}
private void pushOperand(Integer number) {
stack.push(number);
}
private Number doOperate(char oper) {
Integer right = stack.pop();
Integer left = stack.pop();
Integer result = null;
if (left != null && right != null) {
switch (oper) {
case '+':
result = left.intValue() + right.intValue();
break;
case '-':
result = left.intValue() - right.intValue();
break;
case '*':
result = left.intValue() * right.intValue();
break;
case '/':
if (right.intValue() == 0) {
System.err.println("Divide by 0");
}
result = left.intValue() / right.intValue();
break;
default:
break;
}
}
stack.push(result);
return result;
}
private int icp(char c) {
switch (c) {
case '#':
return 0;
case '(':
return 7;
case '*':
return 4;
case '/':
return 4;
case '+':
return 2;
case '-':
return 2;
case ')':
return 1;
default:
return -1;
}
}
private int isp(int c) {
switch (c) {
case '#':
return 0;
case '(':
return 1;
case '*':
return 5;
case '/':
return 5;
case '+':
return 3;
case '-':
return 3;
case ')':
return 7;
default:
return -1;
}
}
public String transfer(String expression) {
StringBuilder sb = new StringBuilder();
SeqStack<Character> stack = new SeqStack<Character>(expression.length());
stack.push('#');
for (int i = 0; i < expression.length(); i++) {
Character c = expression.charAt(i);
if ('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
'A' <= c && c <= 'Z') { // digit character
sb.append(c);
} else { // 操作符
if (icp(c) > isp(stack.top())) { // 進棧
stack.push(c);
} else { // 出棧
if (c == ')') {
char ch = stack.pop();
while (ch != '(') {
sb.append(ch);
ch = stack.pop();
}
} else {
char ch = stack.pop();
while (icp(c) <= isp(ch)) {
sb.append(ch);
ch = stack.pop();
}
stack.push(ch);
stack.push(c);
}
}
}
} // end of for
char ch = stack.pop();
while (ch != '#') {
sb.append(ch);
ch = stack.pop();
}
stack.clear();
return sb.toString();
}
public Integer calc(String expression) {
expression = transfer(expression);
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
switch (c) {
case '+':
case '-':
case '*':
case '/':
doOperate(c);
break;
default:
pushOperand(new Integer(c + ""));
break;
}
}
return stack.pop();
}
/**
* @param args
*/
public static void main(String[] args) {
StackCalc calc = new StackCalc(10);
System.out.println(calc.calc("6/(4-2)+3*2"));
}
}
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
關(guān)于Java如何正確地實現(xiàn)方法重載詳解
在一個類中,可以定義多個構(gòu)造方法,這叫做方法的重載!但是關(guān)于方法重載,具有有哪些要求和細節(jié)?在今天的這篇文章中,小編給大家詳細說說方法重載相關(guān)的內(nèi)容,需要的朋友可以參考下2023-05-05
spring-kafka使消費者動態(tài)訂閱新增的topic問題
這篇文章主要介紹了spring-kafka使消費者動態(tài)訂閱新增的topic問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12
Idea中如何調(diào)出Run dashboard 或services窗口
這篇文章主要介紹了Idea中如何調(diào)出Run dashboard 或services窗口問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
spring cloud 使用Eureka 進行服務(wù)治理方法
這篇文章主要介紹了spring cloud 使用Eureka 進行服務(wù)治理方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
java實現(xiàn)異步回調(diào)返回給前端的方法示例
在Java中實現(xiàn)異步回調(diào)并將結(jié)果返回給前端,通常是在Web應(yīng)用開發(fā)中處理耗時操作時所采用的技術(shù)手段,以避免阻塞HTTP請求線程并提高用戶體驗,本文就來介紹一下如何實現(xiàn),感興趣的可以了解一下2024-03-03
Java線程編程中Thread類的基礎(chǔ)學(xué)習(xí)教程
這篇文章主要介紹了Java線程編程中Thread類的基礎(chǔ)學(xué)習(xí)教程,Thread類包含諸多操作線程的方法,非常重要,需要的朋友可以參考下2015-12-12
圖解Java經(jīng)典算法歸并排序的原理與實現(xiàn)
歸并排序是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide?and?Conquer)的一個非常典型的應(yīng)用。本文將通過動圖詳解歸并排序的原理及實現(xiàn),需要的可以參考一下2022-09-09

