Expression Trees

advertisement
Expression Trees
Purpose:
In this lecture we will discuss Expression trees as a method for storing &
evaluating mathematical expressions
Resources:
Barrons Chapter 10 p.341 plus M/C #s 9, 10, 11
AP Java Text Chapter 19 p.822-826
Handouts:
1.
ExpressionTree.java
Intro:
Expression tree:
Algebraic Expression with parentheses and a defined
precedence of operations
A nested structure that can be represented by a Binary
(expression) Tree
Example:
Operator + - * /
/
\
1st
2nd
operand operand
a + b can be represented as:
+
/
a
\
b
Each node of the Exp tree contains a “TOKEN” which is either an
operator (+ - * /) or an operand ( some number)
The operator can be either unary or binary( + - * / )
The operand can be a variable or a number
Example:
( a + 1 ) * (b * c + 5 – c )
USE TO RUN CODE: ( 4 + 1 ) * (3 * 2 + 5 – 2 )
ANS: 45.0
can be represented as:
*
/ \
+
/ \ / \
a 1 + c
/ \
* 5
/ \
b c
Operators are represented by nodes with children
Operands are represented by leaves
The root of the tree (top most level) contains the LAST operation to execute so
the higher the level number the HIGHER the precedence
Evaluating Expressions Represented by Trees:
The evaluation of an expression tree includes calculating the value of an
expression when given values for the operands’ variables.
Recursion is the easiest way to implement an evaluation function for expression
trees.
Here is the process:
 If a node is an operand, we fetch its value
 If a node is an operator, we apply that operator to the results of an
evaluation of its left and right subtrees
OPERANDS are represented by LEAF nodes
OPERATORS are represented nodes with children
/
b
* ---- operator
\
c ----- operands
CODE EXAMPLE “ExpressionTree.java”:
function
Walk thru the code’s evaluate
*** Assume operands & operators are represented by character strings in tree
nodes ***
String value = (String) node.getValue ();
double leftValue, rightValue;
if (value.equals ("+"))
{
leftValue = evaluate (node.getLeft ());
rightValue = evaluate (node.getRight ());
return leftValue + rightValue;
}
else
return Double.parseDouble (value);
// IN SPVM
TreeNode exprTree;
// Convert the expression into a tree.
exprTree = (TreeNode) TreeUtil.createExpressionTree (expr);
result = evaluate (exprTree);
System.out.println ("Result = " + result);
PREFIX , POSTFIX & INFIX Notations:
INFIX Notation: (LNR)
An inorder traversal of an expression tree printed out fully parenthesized
Conventional algebraic notation where an operator is placed BETWEEN the
operands
x+y
Evaluation of this type of expression requires a recursive evaluation of subtrees
OPUTPUT:
Infix Notation: ( a + 1 ) * ((( b * c ) + 5 ) - c )
Prefix and Postfix:
Convenient for evaluating expressions:
 they do not use parenthesis
 do not need to take into account order of precedence
 order of operations can be reconstructed from the expression
These notations for an algebraic expression can be generated by traversing the
expression in preorder (for prefix) and postorder (for postfix)
PREFIX Notation: (NLR)
Place the operator BEFORE the operands
+xy
There is no need for parenthesis as there is only 1 way to correctly place them
OUTPUT:
Prefix Notation: * + a 1 - + * b c 5 c
Prefix notation is also called Polish Notation
POSTFIX Notation: (LRN)
Place the operator AFTER the operands
xy+
example:
a1+bc*5+c–*
is evaluated in the order:
(a 1 +) (((b c *) 5 +) c -) *
However, there is no need for parenthesis as there is only 1 way to correctly place
them
OUTPUT:
Postfix Notation: a 1 + b c * 5 + c - *
Postfix notation is also called Reverse Polish Notation(RPN)
Evaluation of an Expression using Prefix and Postfix:
Prefix & Postfix allow us to evaluate an algebraic expression in a single, sequential
swipe:
POSTFIX Notation can be evaluated:
Proceed from LEFT to RIGHT using a temporary STACK for holding
unused operands and intermediate results
Algorithm:
 going from LEFT to RIGHT consider the next token
 if it is an operand (#) push its value on the stack
 if it is an operator:
 pop the second operand
 pop the first operand
 perform the operation
 push the result on the stack
we will be left with one value on the stack ---- the result of the
evaluation
EXAMPLE:
a1+bc*5+c-*
Stack’s evolution showing the state of the stack AFTER each token is
encountered (DRAW ON BOARD):
PREFIX Notation can be evaluated:
Proceed from RIGHT to LEFT using a temporary STACK for holding
unused operands and intermediate results
Algorithm:
 going from RIGHT to LEFT consider the next token
 if it is an operand (#) push its value on the stack
 if it is an operator:
 pop the first operand
 pop the second operand
 perform the operation
 push the result on the stack
we will be left with one value on the stack ---- the result of the
evaluation
NOTE: the operands appear in the same order in infix, prefix and postfix notations. Only
the position of the operators is different.
Infix Notation: ( a + 1 ) * ((( b * c ) + 5 ) - c )
Prefix Notation: * + a 1 - + * b c 5 c
Postfix Notation: a 1 + b c * 5 + c - *
Build an expression tree from a postfix expression:
Instead of numbers, we push references to nodes on the stack, instead of
performing an operation, we link the operator node to the nodes of the operands.
Algorithm:
 going from LEFT to RIGHT consider the next token
 Create a new node for the token
 If it is an operand:
 Set the LEFT and RIGHT children to null
 Push the node to the new node on the stack

If it is an operator:
 Pop a pointer from a stack
 Set the new node’s RIGHT child to it
 Pop another reference from the stack
 Set the new node’s LEFT child to it
 Push the reference to the new node on the stack
At the end, the reference to the root of the tree will be the only remaining element
on the stack.
If we want to convert an expression from POSTFIX notation into PREFIX
notation, we can build the expression tree using the previous algorithm and then
traverse the tree in PREORDER
Download