在很多情况下,我们都会认为我们的数据结构比较偏向底层开发,偏向C语言,但是实际上很多情况下,我们的JAVA等高级语言都会在平时的算法中使用到的数据结构,那么我就跟大家在这里使用一下.至于逆波兰表示法又称后缀表示法,在我们的计算机计算的时候,计算机是很机械化的,他没法灵巧运用人的灵活.比如说(5-1)*6+1这么一个数学题,现在的小学生我估计三年级都会了,不然还怎么玩LOL,对吧.
但是如果我们对代码不作处理,计算器怎么可能知道计算的是5-1先还是乘法优先,所以我们就需要用到逆波兰表示法,正好逆波兰表示法又是基于栈来实现的.那么今天我们就来灵活应用,起码别人问到,我们都可以灵活回答,对吧.
public class Test {
//方法:使用链式堆栈,设计一个算法计算表达式
public static void expCaculate(LinkStack stack) throws Exception {
char ch; //扫描每次输入的字符。
int x1, x2, b = 0; //x1,x2:两个操作数 ,b字符的ASCII码
System.out.println("输入后缀表达式并以#符号结束:");
while ((ch = (char) (b = System.in.read())) != '#') {
//如果是数字,说明是操作数则压入堆栈
if (Character.isDigit(ch)) {
stack.push(new Integer(Character.toString(ch)));
}
//如果不是数字,说明是运算符
else {
x2 = ((Integer) stack.pop()).intValue();
x1 = ((Integer) stack.pop()).intValue();
switch (ch) {
case '+':
x1 += x2;
break;
case '-':
x1 -= x2;
break;
case '*':
x1 *= x2;
break;
case '/':
if (x2 == 0) {
throw new Exception("分母不能为零!");
} else {
x1 /= x2;
}
break;
}
stack.push(new Integer(x1));
}
}
System.out.println("后缀表达式计算结果是:" + stack.getTop());
}
public static void main(String[] args) throws Exception {
LinkStack stack = new LinkStack();
//(2+3)*(3-1)/2=5的后缀表达式为:23+31-*2/
//方法:键盘输入后缀表达式,输出的得到计算结果
Test.expCaculate(stack);
}
当然,在日常生活中,我们基本上是不会使用后缀表达式的,但是上面的方法却是要我们输入后缀表达式.所以,我们正确的思路是:
中缀表达式—>后缀表达式–>逆波兰表达式
那么我们就区分下这么几种表达式:
前缀表达式:同后缀表达式一样,不包含括号,运算符放在两个运算对象的前面,如:* + 2 1 3 。前缀表达式和后缀表达式其实是差不多的,只不过符号位置不同而已,前缀表达式不是很常见。
当然对于这个表达式的转换是比较难懂的,所以大家一定要不停去思考.
代码:
public class InfixToSuffix {
/**
* 中缀表达式转后缀表达式 只处理了+,-,*,/和括号,没有处理负号及其它运算符,也没对前缀表达式验证。
* 如要处理负号,可对表达式进行预转义处理,当下面条件成立时,将负号换成单目运算符"!" infix.charAt[i]=='-'&&(
* i==0||infix.charAt[i-1]=='(')
* 3*6/4+3
* 3+6-4 3 6 + 4 -
* 3+(6-4/2)*5 3 6 4 2 / - 5 * +
*/
//方法:中缀表达式转成后缀表达式
/**
* 1. 这里使用了JAVA提供的Stack栈对象
* 2. 遍历字符串,然后根据需求,遇到什么出栈,遇到什么不出栈,这里这个可以作为一个工具类
*
* @param infix
* @return
*/
public static String infixToSuffix(String infix) {
Stack stack = new Stack();
String suffix = "";//前缀字符串
int length = infix.length();
for (int i = 0; i < length; i++) {//遍历字符串
Character temp;
char c = infix.charAt(i); //判断字节对象
switch (c) {
// 忽略空格
case ' ':
break;
// 碰到'(',push到栈
case '(': //符号进栈
stack.push(c);
break;
// 碰到'+''-',将栈中所有运算符弹出,送到输出队列中
case '+':
case '-':
while (stack.size() != 0) {
temp = stack.pop(); //就是+ -已经是最低了
if (temp == '(') { //假如遇到(就进站内)
stack.push('(');
break;
}
suffix += " " + temp; //拼接
}
stack.push(c);
suffix += " ";
break;
// 碰到'*''/',将栈中所有乘除运算符弹出,送到输出队列中
case '*':
case '/':
while (stack.size() != 0) {
temp = stack.pop();
if (temp == '(' || temp == '+' || temp == '-') {
stack.push(temp);
break;
} else {
suffix += " " + temp;
}
}
stack.push(c);
suffix += " ";
break;
// 碰到右括号,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号
case ')':
while (stack.size() != 0) {
temp = stack.pop();
if (temp == '(') //遇到左括号就停止
break;
else
suffix += " " + temp;
}
// suffix += " ";
break;
//如果是数字,直接送至输出序列
default:
suffix += c;
}
}
//如果栈不为空,把剩余的运算符依次弹出,送至输出序列。
while (stack.size() != 0) {
suffix += " " + stack.pop();
}
return suffix;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String str = "1+(2-3)*4+10/5";
//调用方法:中缀表达式转成后缀表达式
System.out.println(InfixToSuffix.infixToSuffix(str));
}
}