中綴表達(dá)式的求解需要兩個(gè)棧來存儲,且設(shè)置為泛型,一個(gè)棧存操作數(shù),一個(gè)棧存操作符,需要輸入一個(gè)表達(dá)式字符串并將其轉(zhuǎn)為字符串?dāng)?shù)組以提取有效字符。
節(jié)點(diǎn)類
public class Node<T> {
Node next;
T data;
public Node() {
super();
}
public Node(T data) {
super();
this.data = data;
}
public Node(T data, Node next) {
super();
this.next = next;
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
棧類
public class LinkStack<T> {
private Node<T> top;
public LinkStack() {
super();
// TODO Auto-generated constructor stub
}
public LinkStack(Node top) {
super();
this.top = top;
}
public T getTop() {
return top.data;
}
public void setTop(T data) {
this.top.data= data;
}
public Node push(T data ) {
Node top = this.top;
Node newTop = new Node(data,top);
this.top=newTop;
return top;
}
public boolean isEmpty() {
return this.top==null?true:false;
}
public T pop() throws Exception {
if(this.isEmpty()) {
throw new Exception(" 棧為空,不能彈出");
}
Node popNode = this.top;
this.top=popNode.next;
return (T) popNode.data;
}
public boolean makeEmpty() {
this.top=null;
return false;
}
public T peek() throws Exception {
if(this.isEmpty()) {
throw new Exception("棧為空,不能得到頂部元素");
}
return this.top.data;
}
}
求解類
import java.util.Scanner;
//支持小數(shù)點(diǎn)和負(fù)數(shù)
//1+2(123+6)/2-3
//5+4(6(4-2)-2+63)/2+4(1+2)
//(-1+2)
//5+4(6(4-2)-2+63)/2+4(1+2)+(-7+8)+(-1)
public class Solution {
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(System.in);
//操作數(shù)棧
LinkStack<Integer> OPND = new LinkStack<Integer>();
//操作符棧
LinkStack<Character> OPTR = new LinkStack<Character>();
System.out.println("請輸入一個(gè)中綴表達(dá)式:");
String[] expression = formatInput(input.nextLine());
// 首先,遍歷expression數(shù)組,同時(shí)以下列原則進(jìn)行操作,然后,對棧內(nèi)的剩余數(shù)字進(jìn)行運(yùn)算,直到操作符棧為空
for (String string : expression) {
if(string.length()==0) { // 因?yàn)楦袷交臅r(shí)候是在非數(shù)字符號前后加空格,所以會存在分割出來是空的情況
continue;
}
//如果是操作符則判斷并計(jì)算,包括會計(jì)算左括號里面操作符優(yōu)先級大的表達(dá)式
else if(string.equals("+") || string.equals("-") || string.equals("*")|| string.equals("/")) {// 遇到運(yùn)算符,將棧內(nèi)優(yōu)先級大于等于自己的符號拿出來參與計(jì)算
//這里要注意
while(!OPTR.isEmpty()&&priorityIsBiggerorSame(OPTR.peek()+"",string)) {// 循環(huán)直到??栈蛘咴跅V腥〉絻?yōu)先級相等或較小的符號
computer(OPND,OPTR);
}
OPTR.push(string.charAt(0));//入棧
}
else if(string.equals("(")) {//遇到左括號入棧
OPTR.push('(');
}
else if(string.equals(")")) {//遇到右括號,計(jì)算括號內(nèi)的全部表達(dá)式,循環(huán)直到遇到左括號
if(OPND.isEmpty()) {
throw new Exception("表達(dá)式無意義");
}
while(OPTR.peek() != '(') {
computer(OPND,OPTR);//實(shí)際上該過程一直計(jì)算優(yōu)先級相等的表達(dá)式
}
OPTR.pop();
}
else { //操作數(shù)入棧
OPND.push(Integer.parseInt(string));
}
}
while(!OPTR.isEmpty()) {//將所有符號出棧參與運(yùn)算
computer(OPND,OPTR);
}
System.out.println(OPND.peek());//輸出結(jié)果
}
// 格式化中綴表達(dá)式輸入,即在符號前后添加空格,便于后面的分隔操作
public static String[] formatInput(String s) {
String temp = "";
/*
* 提取出表達(dá)式中有效的字符(非空格),然后在字符后面統(tǒng)一添上一個(gè)空格,方便后面使用靜態(tài)方法String.split()來
* 例如:1 *(2+ 3) /4 -----> 1 * ( 2 + 3 ) / 4
* 你也可以直接使用List類來存儲提取的有效字符 總之最后的目的就是返回一個(gè)數(shù)組,其中存儲的是有效字符
* 每一個(gè)有效數(shù)字由操作數(shù)分隔開
*/
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '+' || c == '-' || c == '*' || c == '/'||c=='('||c==')') {
//如出現(xiàn)-1+3或(-3+4)這種
if(i>0&& s.charAt(i-1)=='('||i==0) {
temp += c;
}
else {
temp += " " + c + " ";
}
}
else
temp += c;// 數(shù)字不用加空格
}
String[] expression=temp.split(" ");
// System.out.println(expression);
return expression;// 分割
}
// 優(yōu)先級判斷,a是否大于b
public static boolean priorityIsBiggerorSame(String a, String b) {
String s = "+- */";
return (s.indexOf(a) - s.indexOf(b)>= 2)||(s.indexOf(a) - s.indexOf(b)==1);
}
public static void computer(LinkStack<Integer> OPND,LinkStack<Character> OPTR) throws Exception {
int v1 = OPND.pop();
int v2=OPND.pop();
Character op=OPTR.pop();
switch (op) {
case '+':
OPND.push(v2 + v1);
break;
case '-':
OPND.push(v2 - v1);
break;
case '*':
OPND.push(v2 * v1);
break;
case '/':
OPND.push(v2 / v1);
break;
}
}
}