仅用于 + - * / ( ) 的中缀表达式
思路:
因为在输入表达式的时候,表达式是字符串。为例遍历字符串方便,可以考虑将其转化成为ArrayList类型的。由于表达式中可能会出现多位数的情况(比如20*3,遍历的时候先遍历2再遍历0,但是20才是一个数),所以定义一个变量numString用来拼接数字。所以代码如下:
public static List<String> infixToList(String s){
List<String> list = new ArrayList<>();
int index = 0; //字符串的索引
String numString;//这里是用来拼接数字的
char ch;// 记录当前遍历到的字符
do {
if ((ch = s.charAt(index))=='+'
||(ch = s.charAt(index))=='-'
||(ch = s.charAt(index))=='*'
||(ch = s.charAt(index))=='/'
||(ch = s.charAt(index))=='('
||(ch = s.charAt(index))==')'){
list.add(""+ch);//如果遍历到的字符是操作符,直接加入到list中
index++;
}else{
//如果遍历到的字符是数,还需要先看他的后一位是不是数
numString = "";
//如果是数,则需要拼接
while (index<s.length()&&((ch = s.charAt(index))>=48 && (ch = s.charAt(index))<= 57)){
numString += ch;
index++;
}
//否则直接加入到list中
list.add(numString);
}
}while (index<s.length());
//最后返回list
return list;
}
转化为ArrayList之后,就可以很方便的遍历了。现在将其转化为后缀表达式。
step 1:我们需要先初始化一个栈s1,一个数组列表s2(为什么是ArrayList最后再解释)
step 2:从头至尾遍历中缀表达式转化的list
step 3:如果遍历到的是一个数,就直接加入到s2;
step 4:如果遍历到的是括号,其中,如果是“(”,入栈s1;如果是“)”,将s1栈顶运算符依次出栈,但是要加入到s2,直到栈顶元素遇到“(”,就将这一对括号丢弃。
step 5:如果遇到的是运算符(±*/),则比较它与s1栈顶元素的优先级。(5.1)如果s1为空,或者栈顶元素为“(”,则直接将运算符入栈;(5.2)如果不满足条件5.1,且运算符的优先级高于栈顶运算符的优先级,也直接将运算符入栈;(5.3)如果不满足5.1和5.2,则先将栈顶运算符出栈并加入到s2中,再转到5.1与新的栈顶元素继续比较。
step 6:重复步骤step 2~5,直到遍历到表达式的最右边即list的最后一个元素
step 7:将s1的运算符依次出栈,并加入到s2中。
step 8:此时s2中的顺序就是后缀表达式的顺序。为什么不用栈来做s2?因为可以发现,在这个过程中,s2并没有删除元素的操作。且,使用ArrayList的话,s2现在的顺序就是后缀表达式的顺序;如果使用栈(先进后出),还得出栈并且正确的后缀表达式,正好与出栈顺序是相反的。直接用ArrayList更加方便。
代码如下:
(1)中缀转后缀(均为ArrayList类型)
public static List<String> infixToSuffix(List<String> infixList){
Stack<String> s1 = new Stack<>();
List<String> s2 = new ArrayList<>();
for (String s : infixList) {//遍历中缀的list
if (s.matches("\\d+")){//采用正则表达式判断是否为一个数
s2.add(s);
}else if (s.equals("(")){
s1.push(s);
}else if (s.equals(")")){
//这里也是peek()不是pop()
while (!s1.peek().equals("(")){
s2.add(s1.pop());
}
s1.pop();
}else {
//s1非空,比较运算符与栈顶元素的优先级
//这里一定要用peek()方法而不是pop()
while (s1.size() != 0 && Priority.priority(s) <= Priority.priority(s1.peek())){
s2.add(s1.pop());
}
s1.push(s);
}
}
//遍历结束,直接将s1的元素出栈加入到s2中
while (s1.size()!=0){
s2.add(s1.pop());
}
return s2;
}
比较优先级的代码
public class Priority {
private static int ADD = 1;
private static int SUB = 1;
private static int MUL = 2;
private static int DIV = 2;
public static int priority(String s){
int result = 0;
switch (s){
case "+":
result = ADD;
break;
case "-":
result = SUB;
break;
case "*":
result = MUL;
break;
case "/":
result = DIV;
break;
default:
break;
}
return result;
}
}
注:这个是学习笔记。