Data Structures, Algorithms, & Applications in Java
Chapter 12, Exercise 41
The infix expression is assumed to be given
as a String.
Every character in the infix string is assumed to be either one of the
permissible operators, one of the permissible delimiters,
or an operand.
The conversion is done using a stack and scanning the infix form from
right to left. The prefix form is also generated from right to left.
Right parentheses and operators will be stacked. So, we need priorities
for a ")" rather than for a "(". We use 0 as the instack priority of a ")" and
3 for its out of stack priority.
When an operand is encountered, the operand is placed
into the prefix form that is being generated (note that the order of operands
in the infix and prefix forms is the same; only the positioning of the
operators differ).
When an operator is encountered it must be pushed on to the stack, because its
left operand is yet to be seen.
However, we must first decide whether some operators on the
stack must be popped first. Operators at the top of the stack
that have an instack priority that is
greater than the outstack priority of the newly encountered operator are to be
popped.
Right parentheses get stacked when encountered; they do not cause any item to
be popped from the stack. A "(" parenthesis results in the popping (and
transmittal to the prefix form) of items at the stak top until we encounter
the first ")". The encountered ")" is discared.
The code is given below.
public class ConvertInfixToPrefix
{
/* An instance of this class is pushed onto the stack.
Along with the character, the in-stack
priority is stored. */
public static class OperatorData
{
public String element;
public int insidePriority;
public OperatorData(String element, int insidePriority)
{
this.element = element;
this.insidePriority = insidePriority;
}
}
// contains all legal operators
static final String OPERATORS = ")*/+-";
static final int[] INSTACKPRIORITY = {0, 2, 2, 1, 1};
static final int[] OUTSTACKPRIORITY = {3, 2, 2, 1, 1};
public static String convertInfixToPrefix(String infixForm)
{
ArrayStack stack = new ArrayStack();
// used to match priorities of operators
ArrayStack stringValue = new ArrayStack();
// stores the prefix expresion
StringBuffer stringBuffer = new StringBuffer();
// '#' with priority 0 is pushed onto the stack
stack.push(new OperatorData("#", 0));
// processes the ith character of the string
for (int i=infixForm.length()-1; i>=0; i--)
{
// the current character is processed
String currentChar = infixForm.substring(i,i+1);
int operatorCheck = OPERATORS.indexOf(currentChar);
if (operatorCheck != -1)
// checks for operator
{
int insidePriority = INSTACKPRIORITY[operatorCheck];
int outsidePriority = OUTSTACKPRIORITY[operatorCheck];
while (((OperatorData)stack.peek()).insidePriority
> outsidePriority)
stringValue.push(((OperatorData)stack.pop()).element);
stack.push(new OperatorData(currentChar, insidePriority));
}
else if (currentChar.equals("("))
{
while ((((OperatorData)stack.peek()).element)
.equals(")") == false)
// pops elements till ")" is reached.
stringValue.push(((OperatorData)stack.pop()).element);
// pops ")"
stack.pop();
}
else
stringValue.push(currentChar);
}
while (!(stack.empty()))
stringValue.push(((OperatorData)stack.pop()).element);
while (!(stringValue.empty()))
// pops elements from stack to create prefix expression
stringBuffer.append((String)stringValue.pop());
// returns prefix form, leaving out the '#'
return (stringBuffer.toString()).substring
(1 , stringBuffer.length());
}
}