用栈计算数学表达式的值

Posted COOL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用栈计算数学表达式的值相关的知识,希望对你有一定的参考价值。

                                    用栈计算数学表达式的值

计算一个简单数学表达式(+ - * / ( ))的结果,有的这些符号的计算,常常需要看优先级来决定先算哪部分,计算机就是这个原理

两个概念:

中缀表达式(infix Expression):运算符写在两个操作数之间(运算符有一定的优先级,可以用圆括号改变运算顺序)

前/后缀表达式(prefix/postfix Expression):运算符写在两个表达式之前/之后(运算符没有优先级,没有括号,遇到运算符对它前面的两个操作数进行求值)

如中缀表达式“6*(8+7)/5”,换成后缀表达式为“6 8 7 + * 5 /”

编程思路:

函数toPostfix(),用运算符栈来存运算符,从中缀表达式第一个字符开始,如果是数字,直接加到postfix,如果是运算符号,判断和栈顶的优先级,不比栈顶的符号优先级低则入栈,(注意:栈中的“(”优先级最低,),否则,要栈顶出栈,如果是左括号,直接入栈,如果是右括号,则出栈,直到栈顶为左括号为止。

函数toValue(),用操作数栈来存数字,从后缀表达式第一个字符开始,是数字,就入栈,是运算符号就用栈顶的两个数计算结果值,结果入栈。

下面是具体代码,可以帮助理解:

       元素存储,我选择用顺序表(SeqList<T>)

  1 //Stack<T>接口
  2 public interface Stack<T> {
  3     public abstract boolean isEmpty();
  4 
  5     public abstract void push(T x); // 元素x入栈
  6 
  7     public abstract T peek(); // 返回栈顶元素
  8 
  9     public abstract T pop(); // 出栈,返回出栈元素
 10 
 11 }
 12 //顺序栈,使用顺序表存储
 13 public class SeqStack<T> implements Stack<T> {
 14     private SeqList<T> list;
 15 
 16     public SeqStack(int length) {
 17         this.list = new SeqList<T>(length); // 构造容量为length的空栈
 18     }
 19 
 20     public SeqStack() {
 21         this(64); // 构造默认容量的空栈,调用上一个构造函数
 22     }
 23 
 24     public boolean isEmpty() {
 25         return this.list.isEmpty();
 26     }
 27 
 28     public void push(T x) { // 顺序表表尾插入元素
 29         list.insert(x);
 30     }
 31 
 32     public T peek() {
 33         return this.list.get(list.size() - 1);
 34     }
 35 
 36     public T pop() {
 37         return list.remove(list.size() - 1);
 38     }
 39 }
 40 //计算数学表达式
 41 public class Calculate {
 42     // 中缀表达式转化成后缀表达式,把运算符进入到运算符栈
 43     public static StringBuffer toPostfix(String infix) {
 44         Stack<String> st = new SeqStack<String>(infix.length());
 45         StringBuffer sb = new StringBuffer(2 * infix.length());
 46         int i = 0;
 47         while (i < infix.length()) {
 48             char ch = infix.charAt(i);
 49             switch (ch) {
 50             case ‘+‘:
 51             case ‘-‘:
 52                 while (!st.isEmpty() && !st.peek().equals("("))
 53                     // 栈顶不是“(”,那么都不比"+-"低,都要出栈
 54                     sb.append(st.pop());
 55                 st.push(ch + "");
 56                 i++;
 57                 break;
 58             case ‘*‘:
 59             case ‘/‘:
 60                 while (!st.isEmpty()
 61                         && (st.peek().equals("*") || st.peek().equals("/")))
 62                     sb.append(st.pop());
 63                 st.push(ch + "");
 64                 i++;
 65                 break;
 66             case ‘(‘:
 67                 st.push(ch + "");
 68                 i++;
 69                 break;
 70             case ‘)‘:
 71                 String out = st.pop(); // 出栈,直到为"("
 72                 while (out != null && !out.equals("(")) {
 73                     sb.append(out);
 74                     out = st.pop();
 75                 }
 76                 i++;
 77                 break;
 78 
 79             default:
 80                 while (i < infix.length() && ch >= ‘0‘ && ch <= ‘9‘) {
 81                     sb.append(ch);
 82                     i++;
 83                     if (i < infix.length()) {
 84                         ch = infix.charAt(i);
 85                     }
 86                 }
 87                 sb.append(" ");
 88                 break;
 89             }
 90 
 91         }
 92 
 93         while (!st.isEmpty())
 94             // 剩下的出栈
 95             sb.append(st.pop());
 96         return sb;
 97     }
 98 
 99     // 后缀表达式的计算结果,运算结果入栈
100     public static int toValue(StringBuffer postfix) {
101         Stack<Integer> st = new SeqStack<Integer>(postfix.length());
102         int value = 0;
103         for (int i = 0; i < postfix.length(); i++) {
104             char ch = postfix.charAt(i);
105             if (ch >= ‘0‘ && ch <= ‘9‘) {
106                 value = 0; // 一定要先让value初始值为0
107                 while (ch != ‘ ‘) {
108                     value = value * 10 + ch - ‘0‘; // 字符转化为数值
109                     ch = postfix.charAt(++i); // 如果这个字符为多位数
110                 }
111                 st.push(value);
112             } else {
113                 if (ch != ‘ ‘) {
114                     int y = st.pop(), x = st.pop(); // Integer自动转化为int类型
115 
116                     switch (ch) {
117                     case ‘+‘:
118                         value = x + y;
119                         break;
120                     case ‘-‘:
121                         value = x - y;
122                         break;
123                     case ‘*‘:
124                         value = x * y;
125                         break;
126                     case ‘/‘:
127                         value = x / y;
128                         break;
129 
130                     }
131 
132                     st.push(value);
133                 }
134             }
135 
136         }
137         return st.pop(); // 结果就在栈顶
138 
139     }
140 
141 }

 

以上是关于用栈计算数学表达式的值的主要内容,如果未能解决你的问题,请参考以下文章

数据结构(C语言版)严蔚敏->用栈求解表达式(中缀表达式后缀表达式)

数据结构(C语言版)严蔚敏->用栈求解表达式(中缀表达式后缀表达式)

java简易计算机(用栈实现中缀转后缀,计算后缀表达式)

C语言表达式求值

leetcode-Basic Calculator-224

关于栈实现综合计算器的代码实现和讲解