**Assigned Reading:** none

**Handouts (available on-line):**

**Programs from this lecture:**

**Topics Covered:**

- Discussed the extra credit portion of
Project 5. Some highlights:
- Suppose that we have a Binary Search Tree (BST) that satisfies the
condition that at every subtree with 5 or more nodes, neither subtree is
more than twice the size of the other subtree. We argued that the height of
such a BST is O(log n). In fact, it is roughly log
_{(3/2)}n. - Since the height of such a balanced tree is O(log n), BST operations
such as find and max take O(log n) time.
- Insert and delete might take O(n) time in the worst case, since we may
have to rebalance the tree during an insertion or a deletion.
- However, not every insert and delete would require us to rebalance the
tree. We argued (not very rigorously) that on average the running time of
insert and delete is also O(log n). This average is taken over the
operations performed on the BST (we are not taking the average over the
data stored in the tree). In such a situation, we say that the
*amortized running times*of insert and delete are O(log n).

- Suppose that we have a Binary Search Tree (BST) that satisfies the
condition that at every subtree with 5 or more nodes, neither subtree is
more than twice the size of the other subtree. We argued that the height of
such a BST is O(log n). In fact, it is roughly log
- Another kind of binary tree is an expression tree --- a
representation of arithmetic expressions. For example, the expression
2 + 3 can be represented as a binary tree with a root labeled with +.
The root would have two children labeled with 2 and 3. For more
complicated arithmetic expressions, the root of the tree is the
operation that is performed last. The left subtree and right subtree
of the root are the left and right operands of that last operation.
For example, in the expression (2 + 3) * (4 + 5), the * is performed
last, so the left and right subtrees represent (2 + 3) and (4 + 5),
respectively.
Note that in an expression tree, we do not need to store parentheses, since the order of evaluation is implicit in the structure of the tree.

- We can use the template Tree class from Lecture 22 to
*instantiate*an expression tree class. Each node of the expression tree will be an object from a Token class which we describe below. We use the expression tree to help us build a calculator program. This program considers operator precedence of * over + and works with nested parentheses. Another feature of this program is its ability to report errors (and point to the location of the syntax error). See sample run. - The calculator program is divided into 2 parts. The parser (header file and implementation) works with higher level
concepts (expressions, terms and factors). The tokenizer (header file and implementation) does the string and character
manipulations for the parser. The TokenStream class is initialized
with a string which contains an arithmetic expression. The member
functions
`look()`and`eat()`allows us to obtain the next syntactic unit of the string (the next number, operator, etc.). This syntactic unit is returned as an object of type Token. - The parser essentially follows the derivation rules for a legal
arithmetic expression. The
*grammar*we use to describe the set of allowed expressions is:Expression -> Term + Expression Expression -> Term - Expression Expression -> Term Term -> Factor * Term Term -> Factor / Term Term -> Factor Factor -> ( Expression ) Factor -> Number

- We showed how a simple expression like (3 + 4) * (72 - 70) can be
derived using the grammar above. This is a mechanical process that is
tedious to do by hand, but perfect for a program to follow.
- Our parser is simply a set of
mutually recursive functions (
`ParseExpression()`,`ParseTerm()`and`ParseFactor()`) that follow the rules for deriving these arithmetic expressions. If any of these functions find an error, it throws an exception. Each of these functions also catches exceptions. When an exception is caught, memory for any partially built expression trees is deallocated. Then the exception is*rethrown*to be caught again and rethrown again ... until the function`Parse()`finally catches the exceptions for the last time. - The function
`evaluate()`recursively computes the value of an expression tree. Thus, we have all the parts of a calculator program. Build an expression tree from an arithmetic expression and use`evaluate()`to determine the value of the expression.

[Previous Lecture] [Next Lecture]

Last Modified: 4 Dec 1998 23:02:40 EST by Richard Chang

Back up to Fall 1998 CMSC 202 Section Homepage