栈的经典应用之一——表达式求值
2010-09-18 01:22
435 查看
最近碰到了个问题,是在论坛里有人问的,问题是求输入表达式的值。上次碰到这个问题,就用一个投机取巧的方法给解决了,现在自己也忘了具体是怎么弄的!昨天有人问,想着来利用数据结构和编译原理方面的知识来解决。可恨,一时半会居然想不起来了,主要是运算符之间的优先级,在编译原理的课件中找到了,下面就是我写的一个简单的实现程序,先记下,日后有机会了再完善!写到这里,突然想起学C的时候的一句话“程序=数据结构+算法”,是啊,看看,程序和具体的语言没有关系啊!所以要先练好内功,九阳神功才是王道啊!
import java.util.Scanner;
import java.util.Stack;
public class Expression {
//运算符之间的优先级,其顺序是+、-、*、/、(、),其中大于号表示优先级高
//,小于号表示优先级低,等号表示优先级相同,感叹号表示没有优先关系
public static final char[][] relation = {{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},{'<','<','<','<','<','=','!'},
{'>','>','>','>','!','>','>'},{'<','<','<','<','<','!','='}};
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入要计算的表达式:");
String exp = input.next();
System.out.println(calc(exp + "#"));
}
/**
*
* @param exp 要计算的表达式
* @return 计算的结果
*/
private static int calc(String exp) {
//操作数栈
Stack<Integer> num = new Stack<Integer>();
//操作符栈
Stack<Character> op = new Stack<Character>();
op.add('#');
int i = 0;
char ch = exp.charAt(i);
while(ch != '#' || op.peek() != '#') {
if(ch >= '0' && ch <= '9') {
num.push(Integer.parseInt(ch + ""));
i++;
} else {
switch(precede(op.peek(), ch)) {
case '<':
op.push(ch);
i++;
break;
case '=':
op.pop();
i++;
break;
case '>':
int num2 = num.pop();
int num1 = num.pop();
int result = operate(num1, op.pop(), num2);
num.push(result);
break;
case '!':
System.out.println("输入的表达式错误!");
return -1;
}
}
ch = exp.charAt(i);
}
return num.peek();
}
private static char precede(char peek, char ch) {
return relation[getIndex(peek)][getIndex(ch)];
}
/**
*
* @param ch 操作符
* @return 操作符的索引,按照+、-、*、/、(、)的顺序
*/
private static int getIndex(char ch) {
int index = -1;
switch(ch) {
case '+':
index = 0;
break;
case '-':
index = 1;
break;
case '*':
index = 2;
break;
case '/':
index = 3;
break;
case '(':
index = 4;
break;
case ')':
index = 5;
break;
case '#':
index = 6;
break;
}
return index;
}
/**
*
* @param num1 第一个运算数
* @param ch 运算符
* @param num2 第二个运算数
* @return 运算结果
*/
private static int operate(int num1, char ch, int num2) {
int result = 0;
switch(ch) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num1 / num2;
break;
}
return result;
}
}
这是去年简单实现的一个程序,里面有个问题,就是只能计算一位数。最近看数据结构的时候想起这个问题来,就想着改进一下,能处理多位数的运算。下面就是在原来程序的基础上改进后的程序,欢迎大家拍砖。
import java.util.Scanner;
import java.util.Stack;
public class Expression {
//运算符之间的优先级,其顺序是+、-、*、/、(、),其中大于号表示优先级高
//,小于号表示优先级低,等号表示优先级相同,感叹号表示没有优先关系
public static final char[][] relation = {{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},{'<','<','<','<','<','=','!'},
{'>','>','>','>','!','>','>'},{'<','<','<','<','<','!','='}};
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入要计算的表达式:");
String exp = input.next();
System.out.println(calc(exp + "#"));
}
/**
*
* @param exp 要计算的表达式
* @return 计算的结果
*/
private static int calc(String exp) {
//操作数栈
Stack<Integer> num = new Stack<Integer>();
//操作符栈
Stack<Character> op = new Stack<Character>();
op.add('#');
int i = 0;
char ch = exp.charAt(i);
while(ch != '#' || op.peek() != '#') {
if(ch >= '0' && ch <= '9') {
num.push(Integer.parseInt(ch + ""));
i++;
} else {
switch(precede(op.peek(), ch)) {
case '<':
op.push(ch);
i++;
break;
case '=':
op.pop();
i++;
break;
case '>':
int num2 = num.pop();
int num1 = num.pop();
int result = operate(num1, op.pop(), num2);
num.push(result);
break;
case '!':
System.out.println("输入的表达式错误!");
return -1;
}
}
ch = exp.charAt(i);
}
return num.peek();
}
private static char precede(char peek, char ch) {
return relation[getIndex(peek)][getIndex(ch)];
}
/**
*
* @param ch 操作符
* @return 操作符的索引,按照+、-、*、/、(、)的顺序
*/
private static int getIndex(char ch) {
int index = -1;
switch(ch) {
case '+':
index = 0;
break;
case '-':
index = 1;
break;
case '*':
index = 2;
break;
case '/':
index = 3;
break;
case '(':
index = 4;
break;
case ')':
index = 5;
break;
case '#':
index = 6;
break;
}
return index;
}
/**
*
* @param num1 第一个运算数
* @param ch 运算符
* @param num2 第二个运算数
* @return 运算结果
*/
private static int operate(int num1, char ch, int num2) {
int result = 0;
switch(ch) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num1 / num2;
break;
}
return result;
}
}
这是去年简单实现的一个程序,里面有个问题,就是只能计算一位数。最近看数据结构的时候想起这个问题来,就想着改进一下,能处理多位数的运算。下面就是在原来程序的基础上改进后的程序,欢迎大家拍砖。
import java.util.Scanner; import java.util.Stack; public class Expression { //运算符之间的优先级,其顺序是+、-、*、/、(、),其中大于号表示优先级高 //,小于号表示优先级低,等号表示优先级相同,感叹号表示没有优先关系 public static final char[][] relation = {{'>','>','<','<','<','>','>'}, {'>','>','<','<','<','>','>'},{'>','>','>','>','<','>','>'}, {'>','>','>','>','<','>','>'},{'<','<','<','<','<','=','!'}, {'>','>','>','>','!','>','>'},{'<','<','<','<','<','!','='}}; public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("请输入要计算的表达式:"); String exp = input.next(); System.out.println(calc(exp + "#")); } /** * * @param exp 要计算的表达式 * @return 计算的结果 */ private static int calc(String exp) { //操作数栈 Stack<Integer> num = new Stack<Integer>(); //操作符栈 Stack<Character> op = new Stack<Character>(); op.add('#'); int i = 0; char ch = exp.charAt(i); boolean flag = false;//判断连续的几个字符是否是数字,若是,就处理成一个数字。这样就能处理多位数的运算了。 while(ch != '#' || op.peek() != '#') { if(ch >= '0' && ch <= '9') { if(flag) { int tmp = num.pop(); num.push(tmp * 10 + Integer.parseInt(ch + "")); } else { num.push(Integer.parseInt(ch + "")); } flag = true; i++; } else { flag = false; switch(precede(op.peek(), ch)) { case '<': op.push(ch); i++; break; case '=': op.pop(); i++; break; case '>': int num2 = num.pop(); int num1 = num.pop(); int result = operate(num1, op.pop(), num2); num.push(result); break; case '!': System.out.println("输入的表达式错误!"); return -1; } } ch = exp.charAt(i); } return num.peek(); } private static char precede(char peek, char ch) { return relation[getIndex(peek)][getIndex(ch)]; } /** * * @param ch 操作符 * @return 操作符的索引,按照+、-、*、/、(、)的顺序 */ private static int getIndex(char ch) { int index = -1; switch(ch) { case '+': index = 0; break; case '-': index = 1; break; case '*': index = 2; break; case '/': index = 3; break; case '(': index = 4; break; case ')': index = 5; break; case '#': index = 6; break; } return index; } /** * * @param num1 第一个运算数 * @param ch 运算符 * @param num2 第二个运算数 * @return 运算结果 */ private static int operate(int num1, char ch, int num2) { int result = 0; switch(ch) { case '+': result = num1 + num2; break; case '-': result = num1 - num2; break; case '*': result = num1 * num2; break; case '/': result = num1 / num2; break; } return result; } }
相关文章推荐
- 用java编写栈的经典应用-表达式求值
- 堆栈经典应用:表达式求值、后缀表达式
- [原创]表达式求值:经典算法 <Java版本>
- 常用数据结构栈的应用—-表达式求值
- 栈的两个应用:括号匹配的检验和表达式求值
- 栈的应用--四则运算表达式求值(java代码)
- 四则运算表达式求值(栈的应用)
- C++栈的应用——后缀表达式求值、中缀表达式到后缀表达式的转换
- 栈的应用之表达式求值
- JavaScript数据结构中栈的应用之表达式求值问题详解
- 表达式求值算法----栈的应用
- 表达式求值 【栈的应用 或 二叉树的应用
- 011.栈应用表达式求值C实例
- 栈应用 表达式求值
- (栈的应用5.2.2)POJ 2106 Boolean Expressions(表达式求值)
- HDU 1237(简单计算器)栈的应用-表达式求值
- 栈在表达式求值中的应用
- STL栈的应用之表达式求值
- 栈的应用_表达式求值_C#实现
- 回顾数据结构之栈的应用-表达式求值