INFS 519 - October 5, 2010

Table of Contents

Reading

This lecture covers material from chapter 9.

Trees

Trees are non-linear data structures. In contrast with linear data structures such as lists, a tree cannot be traversed by visiting every node once.

A tree has a root node and other nodes in the tree are child nodes of either the root or some other node. Each node has exactly one parent node, except the root node which has no parent.

A leaf node is any node in the tree that does not have a child. Nodes that are below the root node but not leaf nodes are internal nodes.

Any node below another node is a descendant of the higher node. Any node above another node is an ancestor of the lower node. Nodes that share the same parent are siblings.

Some trees may limit the number of branches, n, that may come from every node in the tree. Such trees are known as n-ary trees. For example, a binary tree limits each node to a maximum of two children.

Every node has a depth, which is the level it appears in the tree. The root node is depth 0, the children of the root node have depth 1, etc. Level is synonymous with depth.

The height, or order, is the length of the longest path from the root to a leaf. The length of any path through the tree is calculated by counting the number of links between the start and end nodes.

Balanced trees

See examples from board.

A balanced tree has leaves that are all close to the same depth. Usually if all leaves are at depth h, the height of tree, or h-1.

A complete tree is a balanced tree where all leaves at level h are on the left. This is relevant to sorting as we will see in later lectures.

A full is at maximum capacity. All leaves have the same depth, h. For a binary tree with depth n, there are 2n leaf nodes and 2n+1 - 1 nodes total in the tree.

Decisions trees

As a simple use case, consider binary trees use as a decision tree. Every node has two branches, one for yes and another for no.

Tree representations

Let's consider two ways to represent binary trees. Both of these representations could be modified to represent other types of trees.

Array representation

A complete binary tree can be represented with an array by storing the nodes at each level in order from left-to-right.

See example from board.

Convenient characteristics:

  • The root is always at index 0.
  • The parent for the node at index i is at index (i-1)/2.
  • The children for the node at index i are at the indexes 2i+1 and 2i+2.

Note that if we iterate over the array we are traversing the tree by looking at every node at some level in the tree before moving down to the next level.

Node representation

Similar to the linked list ADT, we can implement a tree using node objects where the tree structure is represented by connections between nodes.

For a binary tree, we have a root node which is similar to the head node in a linked list since they both serve as the starting point for traversing the data structure.

class BTNode<E> {
    private E data;
    private BTNode<E> left;
    private BTNode<E> right;
}

Review implementation on board.

A few examples are included in these notes.

public boolean isLeaf() {
    return (left == null) && (right == null);
}

Use recursion to get data from the leftmost node.

See board (or book, page 456) for example.

public E getLeftmostData() {
    if (left == null) {
        return data;
    }
    else {
        return left.getLeftmostData();
    }
}

Removing a node takes some care to ensure the tree structure remains intact.

See board (or book, page 458) for example.

n.setRight(n.getRight().removeLeftmost());

Recursion is also used in removeLeftMost.

public BTNode<E> removeLeftmost() {
    if (left == null) {
        return right;
    }
    else {
        left = left.removeLeftmost();
        return this;
    }
}

Tree traversals

There are two kinds of tree traversals: depth-first and breadth-first. In depth-first traversals, nodes at deeper levels are accessed before some nodes at shallower levels. In breadth-first traversal all the nodes on each level are accessed before moving to deeper levels.

There are three common ways of depth-first traversal: preorder, inorder, and postorder.

  • Preorder
    1. Process the root.
    2. Process the nodes in the left subtree with recursion.
    3. Process the nodes in the right subtree with recursion.
  • Inorder
    1. Process the nodes in the left subtree with recursion.
    2. Process the root.
    3. Process the nodes in the right subtree with recursion.
  • Postorder
    1. Process the nodes in the left subtree with recursion.
    2. Process the nodes in the right subtree with recursion.
    3. Process the root.

See page 478 for three different traversals of the same tree.

Binary search trees

A binary search tree is a binary tree where every node n follows these rules:

  1. Every element in n's left subtree is less than or equal to the element in node n.
  2. Every element in n's right subtree is greater than the element in node n.

See examples on board.

HTML generated by org-mode 6.35i in emacs 23