Lecture Notes 11: More trees 3/6

Expression trees

Correspond to arithmetic expression. The label in an internal node is an operator, which operates on the expressions in the left and right subtrees. The label on a leaf is a number. To simplify programming, we put that in a separate field called value.

Evaluate a tree N:

ExpressionTree.java
TestExpressionTree.java

Tree Traversal

Recursive tree traversal

Tree1.java
AnimalGroup1.java
RecursiveTreeTraversal.java

Preorder search using a stack: No additional state

MyStack.java
StackTreeTraversal1.java

Preorder/postorder search using a stack: Additional state

StackTreeTraversal2.java

Note: This is exactly how the run-time system handles function calls. It uses a stack of records. Each record holds the state of an active function call (values of local variables and place within the body of the function.)

Advantage to recursive method: The runtime system takes care of your stack for you. Elegant code. Use the recursive method unless there is a compelling reason not to.

Advantages to explicit stack:

Tree traversal: Resource requirements

Time requirements: Proportional to number of nodes in tree. Overall in the course of the entire search, every downward arc is examined once.

Extra memory:

Stack method: Push a record every time you go down a level and pop it every time you go up. So the maximum number of records in the stack is the neight of the tree.

Recursive method: Same thing. The stack is being manipulated behind the scenes by the run-time system, but it's still there.

Breadth-first search

Start at the root; then go across the first row from left to right; then across the second row from left to right; and so on.

Mammal, Rodent, Carnivore, Primate, Squirrel, Rat, Cat, Dog, Skunk, Gorilla, Human.

That's it.
Initialize a FIFO queue Q to hold the root;
repeat {
    N = pop the first node off Q;
    print N; 
    add N's children to the end of Q;
} until (Q is empty)
BreadthFirstSearch.java
FIFOQueue.java

Unlike depth-first search, that's pretty much the only way to implement it. In particular, there's nothing reasonable that corresponds to the recursive implementation of DFS.

(You might think, "The recursive implementation of DFS is actually using a stack of activation records, so it's just hiding the stack. Maybe if you use a FIFO queue of activation records, you could get the same kind of thing for BFS?" But it turns out that it's hard to make sense of a programming languages that uses a FIFO queue of activation records.)