表达式求值 ## click–>算法思想
- 自定义顺序栈
package ccnu.sqStack;
public class SqStack {
private static final int maxSize = 50; // 栈容量
private int top; // 栈顶指针
private char[] data; // 存放栈元素
public SqStack() {
this.top = -1;
this.data = new char[maxSize];
}
/**
* 判断栈是否为空
*
* @return true表示栈为空,否则不为空
* @see #isFull()
*/
public boolean isEmpty() {
if (top == -1) {
return true;
} else {
return false;
}
}
/**
* 判断栈是否已满
*
* @return true表示栈已满,否则没有满
* @see #isEmpty()
*/
public boolean isFull() {
if (top == (maxSize - 1)) {
return true;
} else {
return false;
}
}
/**
* 栈中元素的个数
*
* @return 当前栈中元素的个数
*/
public int size() {
return top + 1;
}
/**
* 元素出栈
*
* @return 栈顶元素值,如果返回'#',当且仅当栈为空
* @see #push(char)
*/
public char pop() {
if (this.isEmpty()) {
return '#'; // '#'表示栈空
} else {
return data[this.top--];
}
}
/**
* 元素进栈
*
* @param c
* 进栈元素值
* @return true表示进栈成功,否则失败
* @see #pop()
*/
public boolean push(char c) {
if (this.isFull()) {
return false;
} else {
data[++top] = c;
return true;
}
}
/**
* 读取栈顶元素
*
* @return 栈顶元素值,如果为'#',当且仅当栈为空
*/
public char getTop() {
if (this.isEmpty()) {
return '#';
} else {
return data[top];
}
}
/**
* 清空栈
*/
public void clear(){
this.top = -1;
}
}
- 中缀表达式串转换为后缀表达式串
/**
* 将中缀表达式串转换为后缀表达式串
*
* @param infix
* 中缀表达式串
* @return 转换的相应的后缀表达式串
*
*/
public static String infixToPostfix(String infix) {
SqStack ss = new SqStack();
StringBuffer postfix = new StringBuffer(); // 存放后缀表达式串
char c;
for (int index = 0; index < infix.length(); index++) {
if (Character.isDigit(c = infix.charAt(index))) {
postfix.append(c); // 如果是数字直接加入到后缀表达式串中
if ((index < infix.length() - 1) && !Character.isDigit(infix.charAt(index + 1))) {
postfix.append(','); // 提取出不同的操作数
}
} else if (infix.charAt(index) == '(') {
ss.push('('); // 如果为'(',直接入栈
} else if (infix.charAt(index) == ')') {
while ('(' != (c = ss.pop())) {
postfix.append(c); // 如果为')',则依次将栈中运算符加入到后缀表达式串中,直到出现'(',并且将'('出栈
}
} else {
if (getPriority(c = infix.charAt(index)) > getPriority(ss.getTop())) {
ss.push(c); // 当前操作符优先级高于栈顶操作符优先级,直接入栈
} else {
while (!ss.isEmpty() && (getPriority(ss.getTop()) >= getPriority(c = infix.charAt(index))
|| ss.getTop() != '(')) {
postfix.append(ss.pop()); // 若当前栈不为空并且栈顶操作符优先级不小于当前操作符优先级或者当前栈顶不为左括号'(',则依次弹出栈顶操作符
}
ss.push(c); // 将当前操作符入栈(上述三个条件不成立了)
}
}
} // for
while (!ss.isEmpty()) {// 将栈中剩余的所有操作符依次弹出加入到后缀表达式串中
postfix.append(ss.pop());
}
for (int i = 0; i < postfix.length(); i++) {
if ((i + 1) < postfix.length() && postfix.charAt(i) == ',' && !Character.isDigit(postfix.charAt(i + 1))) {
postfix.deleteCharAt(i); // 去除连续操作数中最后一个操作数后的逗号
}
}
return postfix.toString();
}
public static int getPriority(char c) {
if (c == '+' || c == '-') {
return 1; // '+'、'-'优先级为1
}
if (c == '*' || c == '/') {
return 2; // '*'、'/'优先级为2
}
return 0; // 其他操作符优先级为0
}
- 计算表达式串
/**
* 得到对应后缀表达式结果
*
* @param expression
* 后缀表达式串
* @return 表达式结果
*/
public static float calExpression(String expression) {
Stack<Float> s = new Stack<Float>();
StringBuffer num = new StringBuffer();
char c;
for (int index = 0; index < expression.length(); index++) {
if (Character.isDigit(c = expression.charAt(index))) {
num.append(c); // 当前字符为数字,则加入StringBuffer中
} else {
if (num.length() != 0) { // StringBuffer不为空,则将这个数字串转为float并进栈,接着清空StringBuffer中的字符序列
s.push(Float.parseFloat(num.toString()));
num.delete(0, num.length());
}
switch (c) { // 当为四种运算符操作时,将栈顶元素X及其前一个元素出栈Y执行Y<operator>X操作(注意操作数顺序)
case '+':
s.push(s.pop() + s.pop());
break;
case '-':
s.push(-(s.pop() - s.pop()));
break;
case '*':
s.push(s.pop() * s.pop());
break;
case '/':
if (s.peek() == 0) {
System.out.print("无穷大 -->");
return Float.MAX_VALUE;
} else {
s.push(1.0f / (s.pop() / s.pop()));
}
}// switch
}
} // for
return s.peek(); // 返回栈顶元素即为结果
}
- 更新部分代码
public static String infixToPostfix(String infix) {
if(infix == null){
return null;
}
StringBuffer postfix = new StringBuffer();
Stack<Character> chars = new Stack<Character>();
for (int i = 0; i < infix.length(); i++) {
char c = infix.charAt(i);
if (Character.isDigit(c)) { // 数字直接加入
postfix.append(c);
if(i + 1 < infix.length() && !Character.isDigit(infix.charAt(i + 1))){
postfix.append(' ');
}
if(i + 1 == infix.length()){
postfix.append(' ');
}
} else {
while (!chars.isEmpty() && getPriority(c) <= getPriority(chars.peek()) && chars.peek() != '(') { // 当遇到左括号时,无论什么情况都要停止出栈
postfix.append(chars.pop());
}
if(c == ')'){ // 需要将左括号出栈
chars.pop();
}else{ // 非左括号则需要将操作符入栈
chars.push(c);
}
}
}
while (!chars.isEmpty()) {
postfix.append(chars.pop());
}
return postfix.toString();
}
private static int getPriority(char ch){
if(ch == '+' || ch == '-'){
return 1;
}else if(ch == '*' || ch == '/'){
return 2;
}else if(ch == '('){ // ')'的优先级为0,'('优先级最高
return 3;
}else{
return 0;
}
}
public static int calcPostfix(String postfix){
if(postfix == null){
return 0;
}
Stack<Integer> nums = new Stack<Integer>();
for(int i = 0; i < postfix.length(); i++){
char c = postfix.charAt(i);
if(!Character.isDigit(c)){
int num2 = nums.pop();
int num1 = nums.pop();
switch (c) {
case '+':
nums.push(num1 + num2);
break;
case '-':
nums.push(num1 - num2);
break;
case '*':
nums.push(num1 * num2);
break;
case '/':
nums.push(num1 / num2);
break;
default: // 处理空格
break;
}
}else{
int spaceIndex = postfix.indexOf(' ', i);
nums.push(Integer.valueOf(postfix.substring(i, spaceIndex)));
i = spaceIndex;
}
}
return nums.pop();
}
- 测试
public static void main(String[] args) {
System.out.print("12+2-12*((10+2)/10-1)+23 = ");
System.out.println(calExpression(infixToPostfix("12+2-12*((10+2)/10-1)+23")));
}