**Remark**:

The department has asked me to make the following announcements.

- The prerequisites for this course are V22.0102 and V63.0120.
- The final exam is Monday, December 16 10:00-11:50am.

Our complexity analysis will proceed in a somewhat unusual order. Instead of starting with the bottom (the tree methods in 2.3.1, e.g., is Internal(v)) or the top (the traversals), we will begin by analyzing some middle level procedures assuming the complexities of the low level are as we assert them to be. Then we will analyze the traversals using the middle level routines and finally we will give data structures for trees that achieve our assumed complexity for the low level.

Let's begin!

These will be verified later.

- root(), parent(v), isInternal(v), isLeaf(v), isRoot(v), swapElements(v,w), replaceElement(v,e) each take O(1) time.
- The methods returning iterators, namely children(v), elements(), and positions(), each take time O(k), where k is the number of items being iterated over. k=#children for the first method and #nodes for the other two.
- For each iterator, the methods hasNext() and nextObject() take O(1) time. nextObject() sometimes has other names like nextPosition() or nextNode() or nextChild().

**Definitions** of **depth** and
**height**.

- The depth of the root is 0.
- The depth of a non-root v is 1 plus the depth of parent(v).
- The height of a leaf is 0.
- The height of an internal node v is 1 plus the maximum height of the children of v.
- The height of a tree is the height of its root.

**Remark**: Even our definitions are recursive!

From the recursive definition of depth, the recursive algorithm for its computation essentially writes itself.

Algorithm depth(T,v) if T.isRoot(v) then return 0 else return 1 + depth(T,T.parent(v))

The complexity is Θ(the answer), i.e. Θ(d_{v}),
where d_{v} is the depth of v in the tree T.

**Problem Set** #1, Problem 3:

Rewrite depth(T,v) without using recursion.

This is quite easy. I include it in the problem set to ensure
that you get practice understanding recursive definitions.

The following algorithm computes the height of a position in a tree.

Algorithm height(T,v): if T.isLeaf(v) then return 0 else h←0 for each w in T.children(v) do h←max(h,height(T,w)) return h

**Remarks on the above algorithm**

- The loop could (perhaps should) be written as an iterator.
Indeed, it
**is**an iterator. - This algorithm is not so easy to convert to non-recursive form

Why?

It is not tail-recursive, i.e. the recursive invocation is not just at the end. - To get the height of the tree, execute height(T,T.root())

**Theorem**: Let T be a tree with n nodes and let
c_{v} be the number of children of node v. The sum of
c_{v} over all nodes of the tree is n-1.

**Proof**:
This is trivial! ... once you figure out what it is saying.
The sum gives the total number of children in a tree. But this almost
all nodes. Indeed, there is just one exception.

What is the exception?

The root.

**Corollary**: Computing the height of an n-node tree
has time complexity Θ(n).

**Proof**:
Look at the code.

The while loop has c_{v} iterations, so by the theorem the
total number of iterations executed is n-1.

Everything else is Θ(1) per iteration.

Do a few on the board. As mentioned above, becoming facile with
recursion is **vital** for tree analyses.

**Definition**: A **traversal** is a
systematic way of "visiting" every node in a tree.

Visit the root and then recursively traverse each child. More formally we first give the procedure for a preorder traversal starting at any node and then define a preorder traversal of the entire tree as a preorder traversal of the root.

Algorithm preorder(T,v): visit node v for each child c of v preorder(T,c) Algorithm preorder(T): preorder(T,T.root())

**Remarks**:

- In a preorder traversal, parents come before children (which is as it should be :-)).
- If you describe a book as an ordered tree, with nodes for each chapter, section, etc., then the pre-order traversal visits the nodes in the order they would appear in a table of contents.

Do a few on the board. As mentioned above, becoming facile with
recursion is **vital** for tree analyses.

**Theorem**: Preorder traversal of a tree with n nodes
has complexity Θ(n).

**Proof**:
Just like height.

The nonrecursive part of each invocation takes O(1+c_{v})

There are n invocations and the sum of the c's is n-1.

**Homework:** R-2.3

First recursively traverse each child then visit the root. More formerly

Algorithm postorder(T,v): for each child c of v postorder(T,c) visit node v Algorithm postorder(T): postorder(T,T.root())

**Theorem**: Preorder traversal of a tree with n nodes
has complexity Θ(n).

**Proof**:
The same as for preorder.