Infix, Postfix and Prefix notations are three different but equivalent ways of writing expressions. It is easiest to demonstrate the differences by looking at examples of operators that take two operands. This is the usual way we write expressions. For example, the usual rules for associativity say that we perform operations from left to right, so the multiplication by A is assumed to come before the division by D. Similarly, the usual rules for precedence say that we perform multiplication and division before we perform addition and subtraction.
|Published (Last):||6 February 2014|
|PDF File Size:||2.17 Mb|
|ePub File Size:||19.59 Mb|
|Price:||Free* [*Free Regsitration Required]|
As you might expect, there are algorithmic ways to perform the conversion that allow any expression of any complexity to be correctly transformed.
The first technique that we will consider uses the notion of a fully parenthesized expression that was discussed earlier. On closer observation, however, you can see that each parenthesis pair also denotes the beginning and the end of an operand pair with the corresponding operator in the middle. If the addition operator were also moved to its corresponding right parenthesis position and the matching left parenthesis were removed, the complete postfix expression would result see Figure 6.
The position of the parenthesis pair is actually a clue to the final position of the enclosed operator. Then move the enclosed operator to the position of either the left or the right parenthesis depending on whether you want prefix or postfix notation. Figure 8 shows the conversion to postfix and prefix notations. To do this we will look closer at the conversion process. We have already noted that the operands A, B, and C stay in their relative positions.
It is only the operators that change position. The order of the operators in the original expression is reversed in the resulting postfix expression. As we process the expression, the operators have to be saved somewhere since their corresponding right operands are not seen yet. Also, the order of these saved operators may need to be reversed due to their precedence. This is the case with the addition and the multiplication in this example. Since the addition operator comes before the multiplication operator and has lower precedence, it needs to appear after the multiplication operator is used.
Because of this reversal of order, it makes sense to consider using a stack to keep the operators until they are needed. We can now start to see how the conversion algorithm will work. When we see a left parenthesis, we will save it to denote that another operator of high precedence will be coming.
That operator will need to wait until the corresponding right parenthesis appears to denote its position recall the fully parenthesized technique. When that right parenthesis does appear, the operator can be popped from the stack.
As we scan the infix expression from left to right, we will use a stack to keep the operators. This will provide the reversal that we noted in the first example. The top of the stack will always be the most recently saved operator. Whenever we read a new operator, we will need to consider how that operator compares in precedence with the operators, if any, already on the stack. Assume the infix expression is a string of tokens delimited by spaces.
The operand tokens are the single-character identifiers A, B, C, and so on. The following steps will produce a string of tokens in postfix order.
Create an empty stack called opstack for keeping operators. Create an empty list for output. Convert the input infix string to a list by using the string method split. Scan the token list from left to right. If the token is an operand, append it to the end of the output list. If the token is a left parenthesis, push it on the opstack. If the token is a right parenthesis, pop the opstack until the corresponding left parenthesis is removed.
Append each operator to the end of the output list. However, first remove any operators already on the opstack that have higher or equal precedence and append them to the output list. When the input expression has been completely processed, check the opstack. Any operators still on the stack can be removed and appended to the end of the output list.
This dictionary will map each operator to an integer that can be compared against the precedence levels of other operators we have arbitrarily used the integers 3, 2, and 1. The left parenthesis will receive the lowest value possible. This way any operator that is compared against it will have higher precedence and will be placed on top of it. Line 15 defines the operands to be any upper-case character or digit.
The complete conversion function is shown in ActiveCode 1. In this case, a stack is again the data structure of choice. However, as you scan the postfix expression, it is the operands that must wait, not the operators as in the conversion algorithm above. Another way to think about the solution is that whenever an operator is seen on the input, the two most recent operands will be used in the evaluation. As you scan the expression from left to right, you first encounter the operands 4 and 5.
At this point, you are still unsure what to do with them until you see the next symbol. Placing each on the stack ensures that they are available if an operator comes next. In this case, the next symbol is another operand. So, as before, push it and check the next symbol. This means that the two most recent operands need to be used in a multiplication operation. By popping the stack twice, we can get the proper operands and then perform the multiplication in this case getting the result We can now handle this result by placing it back on the stack so that it can be used as an operand for the later operators in the expression.
When the final operator is processed, there will be only one value left on the stack. Pop and return it as the result of the expression. Figure 10 shows the stack contents as this entire example expression is being processed.
There are two things to note in this example. First, the stack size grows, shrinks, and then grows again as the subexpressions are evaluated. Second, the division operation needs to be handled carefully. Recall that the operands in the postfix expression are in their original order since postfix changes only the placement of operators. When the operands for the division are popped from the stack, they are reversed. The output will be an integer result. Create an empty stack called operandStack.
Convert the string to a list by using the string method split. If the token is an operand, convert it from a string to an integer and push the value onto the operandStack. Pop the operandStack twice. The first pop is the second operand and the second pop is the first operand. Perform the arithmetic operation. Push the result back on the operandStack. When the input expression has been completely processed, the result is on the stack. Pop the operandStack and return the value.
The complete function for the evaluation of postfix expressions is shown in ActiveCode 2. To assist with the arithmetic, a helper function doMath is defined that will take two operands and an operator and then perform the proper arithmetic operation.
Using these programs as a starting point, you can easily see how error detection and reporting can be included. We leave this as an exercise at the end of the chapter.
Infix, Postfix and Prefix
Data Structure - Expression Parsing
Data Structure : Infix, Postfix and Prefix
Conversion of Infix expression to Postfix expression using Stack data structure