JAVA实现表达式字符串求结果
这里主要实现0~9以及结果是整数的情况下,具体实现可以根据自己情况改
在求表达式前,我们需要学会一个数据结构和几个名词
数据结构-栈
栈,先进后出的一种基于数组的结构,他由数组和末尾的索引组成。这样看起来很抽象,但我们可以想象一下,像生活中的在拥挤的电车里或者窄长的电梯里,最后一个进去的人总是第一个人出去。
进去人的时候我们叫他进栈、入栈或压栈,出来人的时候我们叫他出栈或退栈。最靠近门的人的位置叫做栈顶,最里面的人的位置交栈底。这里用一下度娘的图。
栈在java里用类可以表示为:(JDK自带Stack)一下仅为演示
public class MyStack<E> {
Object[] elementData = new Object[100];//用于储存信息的数组,预计栈中长度超不过100
int elementCount = 0; //栈顶的下一个位置
int top = -1; //栈顶位置
public MyStack() {
}
/**
* 入栈,加入数据
* @param item
*/
public void push(E item) {
elementData[elementCount++] = item;//放数据
top++;//栈顶在top位
}
/**
* 出栈,并返回栈顶是什么
* @return
*/
public E pop() {
E obj = (E) elementData[top];
top --;
elementCount--;
return obj;
}
/**
* 返回栈顶变量
*/
public E peek() {
return (E) elementData[top];
}
}
几个名词
- 中缀表达式: (百度)操作符是以中缀形式处于操作数的中间 ,说白了就是咱平时看到的数学表达式,像1+2*(3+4)/5。(老整这些名词像是怕谁万一听懂了一样→n→)
- 后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行 。emmm…就像3+4吧,转换成后缀表达式就是3 4 +,两个数一个运算符这么个结构。
- 后缀表达式还有个名字,叫逆波兰式 ,以后可以用这个词装装逼→v→
- 优先级:谁数高谁先呗(当我凑字数)。
运算法则
优先级 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
栈内 | # | ( | ) | + - | * / | ||
栈外 | # | ) | + - | * / | ( |
- 首先在栈把“#”进行压栈,并在中缀表达式追加“#”。“#”作为结束标志。
- 对中缀表达式进行遍历,遇到数字进行输出到后缀表达式中
- 如果遇到运算符,把 栈顶的元素的栈内优先级 与 即将入栈元素的栈外优先级 进行比较,如果 栈顶的元素 小,则运算符入栈,否则,则把 栈顶元素 出栈并输出到后缀表达式中,然后把 即将入栈元素 入栈。(良心短句有木有→v→
- 循环前两步直至中缀表达式的尾部的“#”。
注意,前面说过,后缀表达式没有括号!!!
后缀表达式的计算
先遍历后缀表达式,碰到的数字让他入栈,每当遇到运算符的时候,取出两个栈用这个运算符运算,结果入栈,一直到结束标记#为止
代码
用到上面写的MyStack< E >
/**
* 目前只支持求整数,只提供思路,具体功能可以自己加
* @author 絕了千年良緣
*
*/
public class Deom {
/**
* 中缀表达式->后缀表达式
* @param infixExp 中缀表达式
* @return 结果
*/
public static String calculate_postfixExp(String infixExp) {
//栈外优先级
int addsub = 2;//加减
int muldiv = 4;//乘除
int pound = 0;//井号
int left_bracket = 6;//前括号
int right_bracket = 1;//后括号
StringBuffer postfixExp = new StringBuffer("");//后缀表达式
MyStack<Character> stack = new MyStack<>();//栈
stack.push('#');//标记
char[] ife = infixExp.toCharArray();
for (char c : ife) {//遍历
if (c>'0'&&c<'9') {//如果是数,直接加进去
postfixExp.append(c);
}else if (isoperator(c)) {//如果是运算符
switch (c) {//哪那种字符串,以及出栈入栈的处理
case '+':if (whichoperator(stack.peek())<addsub) {stack.push(c);}
else {pop(stack, addsub, postfixExp,c);} ;break;
case '-':if (whichoperator(stack.peek())<addsub) {stack.push(c);}
else {pop(stack, addsub, postfixExp,c);} ;break;
case '*':if (whichoperator(stack.peek())<muldiv) {stack.push(c);}
else {pop(stack, muldiv, postfixExp,c);} ;break;
case '/':if (whichoperator(stack.peek())<muldiv) {stack.push(c);}
else {pop(stack, muldiv, postfixExp,c);} ;break;
case '#':if (whichoperator(stack.peek())<pound) {stack.push(c);}
else {pop(stack, pound, postfixExp,c);} ;break;
case '(':if (whichoperator(stack.peek())<left_bracket) {stack.push(c);}
else {pop(stack, left_bracket, postfixExp,c);} ;break;
case ')':if (whichoperator(stack.peek())<right_bracket) {stack.push(c);}
else {pop(stack, right_bracket, postfixExp,c);} ;break;
}
}
}
System.out.println("后缀表达式:"+postfixExp.toString());
return postfixExp.toString();
}
/**
* 判断是不是有效符号运算符
*/
public static boolean isoperator(char c) {
if (c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='#') {
return true;
}
return false;
}
/**
* 返回该字符的站内优先级
* @param c
* @return
*/
public static int whichoperator(char c) {
//栈内优先级
int addsub = 3;//加减
int muldiv = 5;//乘除
int pound = 0;//井号
int left_bracket = 1;//前括号
int right_bracket = 2;//后括号
switch (c) {
case '+':return addsub;
case '-':return addsub;
case '*':return muldiv;
case '/':return muldiv;
case '(':return left_bracket;
case ')':return right_bracket;
case '#':return pound;
}
return 12138;//用不到,但报错就很难受啊
}
/**
* 出栈操作
* @param stack 栈
* @param num 栈外优先级
* @param postfixExp 后缀表达式
*/
public static void pop(MyStack<Character> stack ,int num,StringBuffer postfixExp,char c) {
while (whichoperator(stack.peek())>=num) {
if (stack.peek()!='('||stack.peek()!=')') {//除去括号
postfixExp.append(stack.pop());
}
}
stack.push(c);//记得让这个符号入栈
}
/**
* 后缀表达式->结果
* @param postfixExp 后缀表达式
* @return 运算结果
*/
public static int calculate(String postfixExp) {
char[] c = postfixExp.toCharArray();
MyStack<Integer> num = new MyStack<>();//用于存放数的栈
for (int i = 0; i < c.length; i++) {//遍历后缀表达式
if (c[i]>='0'&&c[i]<='9') {//如果是数
num.push((int)c[i]-48);//进栈
}else if (c[i]!='#') {//如果是非#的运算符
switch (c[i]) {//出栈出两个数算,并将结果进栈
case '+':num.push(num.pop()+num.pop());break;
case '-':num.push(num.pop()-num.pop());break;
case '*':num.push(num.pop()*num.pop());break;
case '/':num.push(num.pop()/num.pop());break;
}
}
}
return num.pop(); //此时栈中只有一个数,那就是结果
}
public static void main(String[] args) {
System.out.println("请输入表达式:");
Scanner sc = new Scanner(System.in);
String equation = sc.nextLine();
int result =calculate(calculate_postfixExp(equation));
System.out.println("结果是:"+result);
}
}
最后,真爽