波兰式介绍

波兰式是在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之前,所以,这种表示法也称为前缀表达式。

逆波兰式介绍

逆波兰式(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)


其不同的地方只是运算符的位置不同

举个例子2+3为波兰式,23+就为逆波兰式

其转换方法为

24-咸鱼学Java-栈的应用-波兰式转逆波兰式_运算符


这种操作类似于

原式

操作


结果

操作后原式

2+3*5-4*(5-3)

2为数字,直接放入结果

2

+3*5-4*(5-3)

+3*5-4*(5-3)

​+​​​为操作符且栈为空 ​​+​​入栈

​+​

2

3*5-4*(5-3)

3*5-4*(5-3)

3为数字,直接放入结果

​+​

23

*5-4*(5-3)

*5-4*(5-3)

​*​​​和栈内​​+​​​进行比较 ​​*​​​优先级大 ​​*​​入栈

​+*​

2

5-4*(5-3)

5-4*(5-3)

5为数字,直接放入结果

​+*​

235

-4*(5-3)

-4*(5-3)

​-​​​和栈内​​*​​​比较 ​​*​​​优先级大​​*​​出栈

​+​

235*

-4*(5-3)

-4*(5-3)

​-​​​和栈内​​+​​​比较 ​​+​​​优先级大 ​​+​​出栈

235*+

-4*(5-3)

-4*(5-3)

​-​​​为操作符且栈为空 ​​-​​入栈

​-​

235*+

4*(5-3)

4*(5-3)

4为数字,直接放入结果

​-​

235*+4

*(5-3)

*(5-3)

​*​​​和栈内​​-​​​比较 ​​*​​​优先级大 ​​*​​入栈

​-*​

235*+4

(5-3)

(5-3)

​(​​​和栈内​​*​​比较 (优先级大 (入栈

​-*(​

235*+4

5-3)

5-3)

5为数字,直接放入结果

​-*(​

235*+45

-3)

-3)

​-​​​和栈内​​(​​​比较 ​​-​​​优先级大 ​​-​​入栈

​-*(-​

235*+45

3)

3)

3为数字,直接放入结果

​-*(-​

235*+453

)

)

​)​​​和栈内​​-​​​比较 ​​-​​​优先级大 ​​-​​出栈

​-*(​

235*+453-

)

)

​)​​​和栈内​​)​​​比较 ​​(​​​和​​)​​​优先级相等 ​​(​​出栈

​-*​

235*+453-

原式处理完毕栈不为空,逐个弹出

235*+453-*-

结果​​235*+453-*-​

代码实现

stack

package time20180506;
/**
* 栈
* @author 焦焱
*
*/
public class Stack {
/**
* 栈顶标记
*/
int top;
/**
* 栈内元素
*/
char[] elem;
/**
* 无参构造
*/
public Stack()
{
this(10);
}
/**
* 有参构造
* @param size
*/
public Stack(int size) {
this.top = 0;
this.elem = new char[size];
}

/**
* 入栈
* @param val
* @return
*/
public boolean push(char val)
{ //先判断是否满
if(isFull()){
return false;
}
//如果不为空,赋值,并且栈顶往上走一位
this.elem[this.top++] = val;
return true;
}
/**
* 出栈
* @return
*/
public char pop() {
//先判断是否为空
if(isEmpty()){
System.out.println("当前栈为空");
return '/' ;
}
//返回当前栈顶减一位置的的元素,并且栈顶往下减一。
return elem[--top];
}
/**
* 获得栈顶元素
* @return
*/
public char getTop()
{ //如果为空返回-1,如果
return isEmpty()?'/':elem[this.top-1];
}
/**
* 判断是否满
* @return
*/
public boolean isFull()
{
return top==this.elem.length;
}
/**
* 判断是否空
* @return
*/
public boolean isEmpty()
{
return top==0;
}
/**
* 显示当前栈内所有元素
*/
public void show()
{
System.out.println("\t栈顶------->栈底");
System.out.print("当前栈数据为:");
for (int i = top-1; i >=0; i--) {
System.out.print(elem[i]+" ");
}
System.out.println();
}
}

bolan

package time20180506;

/**
* 逆波兰式
* @author 焦焱
*
*/
public class Bolan {
//优先级越高值越小
/**
* 栈内加法
*/
public static final int OPERATORS_PRIO_PLUS_IN = 4;
/**
* 栈内减法
*/
public static final int OPERATORS_PRIO_SUB_IN = 4;
/**
* 栈内乘法
*/
public static final int OPERATORS_PRIO_MULTY_IN = 2;
/**
* 栈内除法
*/
public static final int OPERATORS_PRIO_DIV_IN = 2 ;
/**
* 栈内左括号
*/
public static final int OPERATORS_PRIO_LEFT_BRAK_IN = 10;

/**
* 栈外加法
*/
public static final int OPERATORS_PRIO_PLUS_OUT = 5 ;
/**
* 栈外减法
*/
public static final int OPERATORS_PRIO_SUB_OUT = 5;
/**
* 栈外乘法
*/
public static final int OPERATORS_PRIO_MULTY_OUT = 3;
/**
* 栈外除法
*/
public static final int OPERATORS_PRIO_DIV_OUT = 3;
/**
* 栈外左括号
*/
public static final int OPERATORS_PRIO_LEFT_BRAK_OUT = 1;
/**
* 栈外右括号
*/
public static final int OPERATORS_PRIO_RIGHT_BRAK_OUT = 10;
/**
* 错误
*/
public static final int OPERATORS_PRIO_ERROR = -1;

/**
* 获得其优先级
* @param opera 运算符
* @param instack 是否在栈内
* @return 其优先级,优先级越大值越小
*/
public static int getPrio(char opera,boolean instack)
{
int prio = OPERATORS_PRIO_ERROR;
if(instack)
{
switch(opera)
{
case '+':
prio = OPERATORS_PRIO_PLUS_IN;
break;
case '-':
prio = OPERATORS_PRIO_SUB_IN;
break;
case '*':
prio = OPERATORS_PRIO_MULTY_IN;
break;
case '/':
prio = OPERATORS_PRIO_DIV_IN;
break;
case '(':
prio = OPERATORS_PRIO_LEFT_BRAK_IN;
break;
default:
prio = OPERATORS_PRIO_ERROR;
break;
}
}
else
{
switch(opera)
{
case '+':
prio = OPERATORS_PRIO_PLUS_OUT;
break;
case '-':
prio = OPERATORS_PRIO_SUB_OUT;
break;
case '*':
prio = OPERATORS_PRIO_MULTY_OUT;
break;
case '/':
prio = OPERATORS_PRIO_DIV_OUT;
break;
case '(':
prio = OPERATORS_PRIO_LEFT_BRAK_OUT;
break;
case ')':
prio = OPERATORS_PRIO_RIGHT_BRAK_OUT;
break;
default:
prio = OPERATORS_PRIO_ERROR;
break;
}
}
return prio;
}
/**
* 转换
* @param strMid
* @param strLast
* @return
*/
public static String strMidToLast(String strMid)
{ //栈
Stack stack = new Stack();
//逆波兰式结果
StringBuffer string = new StringBuffer();
//栈内优先级
int prioIn;
//栈外优先级
int prioOut;
//循环遍历strMid
for(int i=0;i<strMid.length();i++)
{ //检查是不是数字,如果为数字,直接放到结果里面
if(Character.isDigit(strMid.charAt(i)))
{
string.append(strMid.charAt(i));
}
else
{ //如果不为数字而且栈为空
if(stack.isEmpty())
{
//将运算符入栈
stack.push(strMid.charAt(i));
}
//如果栈不为空
else
{ //获取栈内的运算符的优先级
prioIn = getPrio(stack.getTop(),true);
//获取栈外的运算符的优先级
prioOut = getPrio(strMid.charAt(i),false);
//如果栈外优先级比栈内的大
if(prioIn < prioOut)
{
//把栈内的运算符弹出,放入结果
string.append(stack.pop());
//因为第i个数据还得和栈的下一个运算符比较
//所以需要手动将其置回
i--;
}
//当两个相等的时候就是栈内左括号和栈外有括号
//只需要将栈内左括号弹出即可
else if(prioIn == prioOut)
{
stack.pop();
}
//当栈外优先级比栈内的小则将其放入栈中
else
{
stack.push(strMid.charAt(i));
}
}
}
}
//如果栈不为空,则其内还有运算符,需要逐个弹出,放到结果后面
while(!stack.isEmpty())
{
string.append(stack.pop());
}
return string.toString();
}
public static void main(String[] args) {
String a = "2+3*5-4*(5-3)";
String strMidToLast = strMidToLast(a);
System.out.println(strMidToLast);
}


}

测试结果​​235*+453-*-​