Algs4-1.3.10中序表达式转为后序表达式(第二次实现)
1.3.10编写一个过滤器InfixToPostfix,将算术表达式由中序表达式转为后序表达式。
答:本次做这个题时离上次做这个题有一个半月了,已经忘记了当时的算法。经过两个小时的研究(远低于第一次的研究时间),得出的算法与上次的算法几乎相同,个别细节有差别,而这个细节正是上一个版本的错误之处。
本次的算法描述如下:
前提:将读入的符分为三类:
1)操作数
2)运算符:运算符有+、-、*、/,^(指数运算)优先级+-相同,*/相同,-小于*,*小于^
3)左括号"("、右括号")"
算法:
有一个Queue和一个Stack结构。
1)不断的读入数据,直到读入空字符串时结束读入。
1.1)如果读入的是操作数,那么入队。
1.2)如果读入的是运算符时
1.2.1)栈为空时,读入的运算符入栈。
1.2.2)栈有内容时
1.2.2.1)栈顶元素是左括号时,将读入的运算符入栈。
1.2.2.2)栈顶元素是运算符,并且其优先级低于本次读入的运算符优先级时,将读入的运算符入栈。
1.2.2.3)栈顶元素是运算符,并且其优先及高于或等于本次读入的运算符优先级时,
1.2.2.3.1)如果栈顶元素 是左括号 或是 优先级大于读入运算符的运算符 或是 栈为空,那么不弹出,否则一直弹 出并将弹出元素入队。结束弹出后,将读入运算符入栈。
1.3)如果读入的时左括号时,入栈。
1.4)如果读入的是右括号,栈元素不断的弹出并将弹出元素入队,直到弹出一个左括号时结束弹出,左括号不入队。
2)读入数据结束后,将栈中元素全部弹出,并将弹出元素入队。
3)出队次序即是后序表达式次序。
输入中序表达式:
1
+
2
*
3
-
4
/
2
+
(
1
+
4
)
输出后序表达式:
1
2
3
*
+
4
2
/
-
1
4
+
+
public class InfixToPostfix
{
public static void main(String[] args)
{
Queue<String> q=new Queue<String>();
Stack<String> s=new Stack<String>();
OperatorManager op=new OperatorManager();
while(!StdIn.isEmpty())
{
String item=StdIn.readString();
if(item.equals("("))
s.push(item);
else if(item.equals(")"))
while(true)
{
String sItem=s.pop();
if(sItem.equals("("))
break;
else
q.enqueue(sItem);
}
else if(op.isOperator(item))
{
if(s.isEmpty())
s.push(item);
else if(s.peek().equals("("))
s.push(item);
else if(op.levelIsBig(item,s.peek()))
s.push(item);
else
{
while(true)
{
if (s.isEmpty())
break;
else if(s.peek().equals("("))
break;
else if(op.levelIsBig(item,s.peek()))
break;
else
q.enqueue(s.pop());
}
s.push(item);
}
}
else//is number
q.enqueue(item);
show(item,q,s);
}//end read
//element of Stack pop to queue.
while(!s.isEmpty())
q.enqueue(s.pop());
show("",q,s);
//show the express of postfix
for(String i:q)
StdOut.println(i);
}//end main
private static void show(String item,Queue<String> q,Stack<String> s)
{
StdOut.printf(item);
StdOut.printf(" Queue:");
for(String i:q)
StdOut.printf(i);
StdOut.printf(" Stack:");
for(String i:s)
StdOut.printf(i);
StdOut.println();
}
}//end class
public class OperatorManager
{
private class Operator
{
String OP;
int level;
}
private Operator[] a=new Operator[5];
public OperatorManager()
{
Operator op0=new Operator();
op0.OP="+";
op0.level=0;
a[0]=op0;
//
Operator op1=new Operator();
op1.OP="-";
op1.level=0;
a[1]=op1;
//
Operator op2=new Operator();
op2.OP="*";
op2.level=1;
a[2]=op2;
//
Operator op3=new Operator();
op3.OP="/";
op3.level=1;
a[3]=op3;
//
Operator op4=new Operator();
op4.OP="^";
op4.level=2;
a[4]=op4;
}
public boolean isOperator(String item)
{
for(int i=0;i<a.length;i++)
if(a[i].OP.equals(item)) return true;
return false;
}
public boolean levelIsBig(String op1,String op2)
{
int op1level=Level(op1);
int op2level=Level(op2);
return op1level>op2level;
}
private int Level(String op)
{
for(int i=0;i<a.length;i++)
{
if(a[i].OP.equals(op))
return a[i].level;
}
return -1;
}
}