栈——表达式求值
通过栈来实现表达式的计算
主要问题在于:运算符的优先级关系处理
算法思想:
1.建立并初始化 运算符栈OPTR栈 和 数值OPND栈,将表达式起始符"#"压入OPTR栈;
2.按序获取表达式数组中每个字符串str(假定表达式是合法有效的):
->如果str表示数值:
直接压入OPND栈,进入下一次for循环;
->如果str表示运算符:
取出OPTR的栈顶运算符 top,比较str和top之间的优先级关系:
->如果优先级关系相等:
->如果top和str的均为"#":
整个表达式求值完毕 return OPND栈顶元素;
->如果栈顶元素是左括号"(",读入str为")":
那么将OPTR栈顶弹出,进入下一次for循环;
->如果top优先级大于str:
弹出OPND栈顶元素2个(b, a),弹出OPTR栈顶元素(top),然后计算:result = a top b;
将result压入OPND栈,将当前数组的遍历下标值减一,进入下一次for循环;
->如果top优先级小于str:
将str压入OPTR栈;
运算符之间的优先级比较:
top\str | + | - | * | / | ( | ) | # |
+ | > | > | < | < | < | > | > |
- | > | > | < | < | < | > | > |
* | > | > | > | > | < | > | > |
/ | > | > | > | > | < | > | > |
( | < | < | < | < | < | = | |
) | > | > | > | > | > | > | |
3 | < | < | < | < | < | = |
Java代码如下:
1 package learn.normalcode; 2 3 import java.util.ArrayList; 4 import java.util.Collections; 5 import java.util.Stack; 6 7 /** 8 * 基础表达式求值(使用2个栈完成) 9 */ 10 public class BlankZ { 11 12 private static int[][] relationTable = new int[50][50]; 13 static { 14 int add = '+' - '!'; 15 int reduce = '-' - '!'; 16 int mu = '*' - '!'; 17 int div = '/' - '!'; 18 int left_K = '(' - '!'; 19 int right_K = ')' - '!'; 20 int jin = '#' - '!'; 21 int[] symbol = {add, reduce, mu, div, left_K, right_K, jin}; 22 for (int i = 0; i < 7; ++i) { 23 // System.out.println(symbol[i]); 24 } 25 for (int i = 0; i < 7; ++i) { 26 relationTable[add][symbol[i]] = 1; 27 relationTable[reduce][symbol[i]] = 1; 28 relationTable[mu][symbol[i]] = 1; 29 relationTable[div][symbol[i]] = 1; 30 relationTable[left_K][symbol[i]] = -1; 31 relationTable[right_K][symbol[i]] = 1; 32 relationTable[jin][symbol[i]] = -1; 33 } 34 relationTable[add][mu] = relationTable[add][div] = relationTable[add][left_K] = -1; 35 relationTable[reduce][mu] = relationTable[reduce][div] = relationTable[reduce][left_K] = -1; 36 relationTable[mu][left_K] = -1; 37 relationTable[div][left_K] = -1; 38 relationTable[left_K][right_K] = 0; 39 relationTable[jin][jin] = 0; 40 } 41 public static boolean strIsSymbol(String str) { 42 char c = str.charAt(0); 43 return str.length() == 1 && !(c >= '0' && c <= '9'); 44 } 45 public static int compare(String topSymbol, String str) { 46 return relationTable[topSymbol.charAt(0) - '!'][str.charAt(0) - '!']; 47 } 48 public static String compute(int num2, int num1, char c) { 49 int result = 0; 50 switch (c) { 51 case '+': 52 result = num1 + num2; 53 break; 54 case '-': 55 result = num1 - num2; 56 break; 57 case '*': 58 result = num1 * num2; 59 break; 60 case '/': 61 result = num1 / num2; 62 break; 63 } 64 return String.valueOf(result); 65 } 66 public static void main(String[] args) { 67 Stack<String> numbers = new Stack<>(); 68 Stack<String> operators = new Stack<>(); 69 70 operators.add("#"); 71 72 String[] arr = {"3", "-", "2", "*", "(", "5", "+", "(", "2", "+", "0", ")", ")", "*", "3", "/", "2", "#"}; 73 ArrayList<String> sentence = new ArrayList<>(11); 74 Collections.addAll(sentence, arr); 75 76 for (int i = 0; i < sentence.size(); ++i) { 77 String str = sentence.get(i); 78 79 if (strIsSymbol(str)) { 80 String topElement = operators.peek(); 81 int compareResult = compare(topElement, str); 82 if (compareResult == 0) { 83 //判断是否是结束符号 # 84 if (str.equals("#")) { 85 operators.pop(); 86 System.out.println(numbers.pop()); 87 return; 88 } else { 89 operators.pop(); 90 } 91 } else if (compareResult > 0) { 92 //取出topElement,以及numbers中的2个顶部元素,进行计算 93 operators.pop(); 94 numbers.add(compute(Integer.valueOf(numbers.pop()), Integer.valueOf(numbers.pop()), topElement.charAt(0))); 95 i--; 96 } else { 97 operators.add(str); 98 } 99 } else { 100 numbers.add(str); 101 } 102 } 103 } 104 }