- C++ Reading: Chapter 7 Trees
- Java Reading: Chapter 8 Trees

A tree is a set of *nodes* in a *parent-child* relationship.

- Each node has a unique
*parent*. - Excepting the
*root*has no parent. - A node \(v\) with parent \(u\) is a
*child*of \(u\). - Two nodes with the same parent are
*siblings*. - A node is
*internal*if it has one or more children. - An
*external*node is also called a*leaf*. - A node \(u\) is an
*ancestor*of \(v\) if \(u = v\) or \(u\) is the ancestor of the parent of \(v\). - A node \(u\) is a
*descendant*of \(v\) if \(v\) is an ancestor of \(u\). - A
*subtree*at node \(v\) is the tree consisting of all descendants of \(v\). - “Descendant” is a noun. “Descendent” is an adjective.
- An
*edge*is a pair of nodes \(u\) and \(v\) such that \(u\) is parent of \(v\) or vice-versa. - A
*path*is a sequence of nodes such that any consecutive pair of nodes form an edge. - The
*depth*of \(v\) is the number of ancestors of \(v\), not counting \(v\) itself. - The
*height*of \(v\) is the distance from \(v\) to its deepest descendant. - The
*height*of a tree is the depth of its deepest external node. - The
*level*\(d\) is the set of all nodes at depth \(d\). - In a
*binary*tree, each node has at most two children. - A binary tree is
*proper*if each node has zero or two children.

A general linked tree structure defines each node with a value, a reference to a parent, and a sequence of references to children.

```
node parent(node v)
sequence& children(node v)
bool isRoot(node v)
bool isExternal(node v)
```

Trees are naturally recursive.

We can also recursively *traverse* a tree, visiting each node in either *pre-order*, *in-order*, or *post-order*. We can also traverse in *depth-first* order using a stack, or *breadth-first* order using a queue.

A binary tree is simplified because it does away with the child sequence.

```
class node
{
T value
node left
node right
}
```

It’s trivially easy to define

```
bool isRoot(node v)
bool isExternal(node v)
```

A note about the textbook’s definition of tree structures: it is very specific in its use of iterators. For example, Code Fragment 7.24 in the C++ book (similar to C.F. 8.22 in the Java). This obsession with iterators is not necessary. A more pure implementation of a pre-order traversal would look more like this:

function binaryPreorder(v)

visit(v)

if v.left exists

binaryPreorder(v.left)

if v.right exists

binaryPreorder(v.right)

An in-order:

function binaryInorder(v)

if v.left exists

binaryInorder(v.left)

visit(v)

if v.right exists

binaryInorder(v.right)

A post-order:

function binaryPostorder(v)

if v.left exists

binaryPostorder(v.left)

if v.right exists

binaryPostorder(v.right)

visit(v)

Here’s an alternative formulation of a pre-order traversal, showing the stack usage explicitly.

\(S\).push(\(v\))

while \(S\) is not empty

\(v\) = \(S\).top()

visit(\(v\))

\(S\).pop()

if \(v\).right exists

\(S\).push(\(v\).right)

if \(v\).left exists

\(S\).push(\(v\).left)

Here’s the same pre-order traversal, but with a queue instead of a stack. Note that breadth-first traversal emerges naturally.

\(Q\).enqueue(\(v\))

while \(Q\) is not empty

\(v\) = \(Q\).front()

visit(\(v\))

\(Q\).dequeue()

if \(v\).right exists

\(Q\).enqueue(\(v\).right)

if \(v\).left exists

\(Q\).enqueue(\(v\).left)

We can easily define recursive algorithms to give the depth and height of a node. The height of a proper binary tree:

function computeHeight(node \(v\))

if \(v\).isExternal()

return 0

else

return 1 + max(computeHeight(\(v\).left), computeHeight(\(v\).right)

The height of an improper binary tree:

function computeHeight(node \(v\))

if \(v\).left and \(v\).right

return 1 + max(computeHeight(\(v\).left), computeHeight(\(v\).right)

else if \(v\).left

return 1 + computeHeight(\(v\).left)

else if \(v\).right

return 1 + computeHeight(\(v\).right)

else

return 0

The following properties must hold for node count \(n\), height \(h\), external count \(n_E\), and internal count \(n_I\).

- \(1 \le n_E \le 2^h\)
- \(h \le n_I \le 2^h - 1\)
- \(h + 1 \le n \le 2^{h+1} - 1\)
- \(\log(n+1) - 1 \le h \le n - 1\)

If a tree is *proper* then:

- \(2h + 1 \le n \le 2^{h+1} - 1\)
- \(h + 1 \le n_e \le 2^h\)
- \(h \le n_I \le 2^h - 1\)
- \(\log(n+1) - 1 \le h \le (n - 1) / 2\)
- If non-empty, \(n_E = n_I + 1\)

The maximum number of nodes at level \(l\) is \(2^l\).

Note, it’s straightforward to define a general tree in terms of a binary tree.

Invariant: All of the values in the left subtree of a node \(v\) are less than or equal to the value at \(v\), while all of the values in the right subtree of a node \(v\) are greater than the value at \(v\).