中缀表达式的求解需要两个栈来存储,且设置为泛型,一个栈存操作数,一个栈存操作符,需要输入一个表达式字符串并将其转为字符串数组以提取有效字符。
节点类
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;
//支持小数点和负数
//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);
//操作数栈
LinkStack<Integer> OPND = new LinkStack<Integer>();
//操作符栈
LinkStack<Character> OPTR = new LinkStack<Character>();
System.out.println("请输入一个中缀表达式:");
String[] expression = formatInput(input.nextLine());
// 首先,遍历expression数组,同时以下列原则进行操作,然后,对栈内的剩余数字进行运算,直到操作符栈为空
for (String string : expression) {
if(string.length()==0) { // 因为格式化的时候是在非数字符号前后加空格,所以会存在分割出来是空的情况
continue;
}
//如果是操作符则判断并计算,包括会计算左括号里面操作符优先级大的表达式
else if(string.equals("+") || string.equals("-") || string.equals("*")|| string.equals("/")) {// 遇到运算符,将栈内优先级大于等于自己的符号拿出来参与计算
//这里要注意
while(!OPTR.isEmpty()&&priorityIsBiggerorSame(OPTR.peek()+"",string)) {// 循环直到栈空或者在栈中取到优先级相等或较小的符号
computer(OPND,OPTR);
}
OPTR.push(string.charAt(0));//入栈
}
else if(string.equals("(")) {//遇到左括号入栈
OPTR.push('(');
}
else if(string.equals(")")) {//遇到右括号,计算括号内的全部表达式,循环直到遇到左括号
if(OPND.isEmpty()) {
throw new Exception("表达式无意义");
}
while(OPTR.peek() != '(') {
computer(OPND,OPTR);//实际上该过程一直计算优先级相等的表达式
}
OPTR.pop();
}
else { //操作数入栈
OPND.push(Integer.parseInt(string));
}
}
while(!OPTR.isEmpty()) {//将所有符号出栈参与运算
computer(OPND,OPTR);
}
System.out.println(OPND.peek());//输出结果
}
// 格式化中缀表达式输入,即在符号前后添加空格,便于后面的分隔操作
public static String[] formatInput(String s) {
String temp = "";
/*
* 提取出表达式中有效的字符(非空格),然后在字符后面统一添上一个空格,方便后面使用静态方法String.split()来
* 例如:1 *(2+ 3) /4 -----> 1 * ( 2 + 3 ) / 4
* 你也可以直接使用List类来存储提取的有效字符 总之最后的目的就是返回一个数组,其中存储的是有效字符
* 每一个有效数字由操作数分隔开
*/
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '+' || c == '-' || c == '*' || c == '/'||c=='('||c==')') {
//如出现-1+3或(-3+4)这种
if(i>0&& s.charAt(i-1)=='('||i==0) {
temp += c;
}
else {
temp += " " + c + " ";
}
}
else
temp += c;// 数字不用加空格
}
String[] expression=temp.split(" ");
// System.out.println(expression);
return expression;// 分割
}
// 优先级判断,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;
}
}
}
网友评论