Trees
- A tree is an abstract model of a heirarchical structure
- A tree consists of nodes with a parent-child relationship
- A parent has one or more children
- Each child has only one parent
- The root is the top node in the tree, the only node without a parent
- An internal node has at least one child
- An external node (or leaf) is a mode with no children
- Nodes have ancestors (ie, the parent node of a parent)
- The depth of a node is its number of ancestors
- The height of a tree is its maximum depth
Tree ADT
Tree ADTs are defined using a similar concept to positional lists, as they don't have a natural ordering/indexing in the same way arrays do.
public interface Tree<E>{
int size();
boolean isEmpty();
Node<E> root(); //returns root node
Node<E> parent(Node<E> n); //returns parent of Node n
Iterable<Node<E>> children(Node<E> n); //collection of all the children of Node n
int numChildren(Node<E> n);
Iterator<E> iterator(); //an iterator over the trees elements
Iterator<Node<E>> nodes(); //collection of all the nodes
boolean isInternal(Node<E> n); //does the node have at least one child
boolean isExternal(Node<E> n); //does the node have no children
boolean isRoot(Node<E> n); //is the node the root
}
Tree Traversal
Trees can be traversed in 3 different orders. As trees are recursive data structures, all 3 traversals are defined recursively. The tree below is used as an example in all 3 cases.
Pre-order
- Visit the root
- Pre order traverse the left subtree
- Pre order traverse the right subtree
Pre-order traversal of the tree gives: F B A D C E G I H
In-order
- In order traverse the left subtree
- Visit the root
- In order traverse the right subtree
In-order traversal of the tree gives: A B C D E F G H I
Post-order
- Post order traverse the left subtree
- Post order traverse the right subtree
- Visit the root
Post-order traversal of the tree gives: A C E D B H I G F
Binary Trees
A binary tree is a special case of a tree:
- Each node has at most two children (either 0, 1 or 2)
- The children of the node are an ordered pair (the left node is less than the right node)
A binary tree will always fulfil the following properties:
Where:
- is the number of nodes in the tree
- is the number of external nodes
- is the number of internal nodes
- is the height/max depth of the tree
Binary Tree ADT
The binary tree ADT is an extension of the normal tree ADT with extra accessor methods.
public interface BinaryTree<E> extends Tree<E>{
Node<E> left(Node<E> n); //returns the left child of n
Node<E> right(Node<E> n); //returns the right child of n
Node<E> sibling(Node<E> n); //returns the sibling of n
}
Arithmetic Expression Trees
Binary trees can be used to represent arithmetic expressions, with internal nodes as operators and external nodes as operands. The tree below shows the expression . Traversing the tree in-order will can be used to print the expression infix, and post-order evaluating each node with it's children as the operand will return the value of the expression.
Implementations
- Binary trees can be represented in a linked structure, similar to a linked list
- Node objects are positions in a tree, the same as positions in a positional list
- Each node is represented by an object that stores
- The element
- A pointer to the parent node
- A pointer to the left child node
- A pointer to the right child node
- Alternatively, the tree can be stored in an array
A
A[root]
is 0- If p is the left child of q,
A[p] = 2 * A[q] + 1
- If p is the right child of q,
A[p] = 2 * A[q] + 2
- In the worst, case the array will have size
Binary Search Trees
- Binary trees can be used to implement a sorted map
- Items are stored in order by their keys
- For a node with key , every key in the left subtree is less than , and every node in the right subtree is greater than
- This allows for support of nearest-neighbour queries, so can fetch the key above or below another key
- Binary search can perform nearest neighbour queries on an ordered map to find a key in time
- A search table is an ordered map implemented using a sorted sequence
- Searches take
- Insertion and removal take time
- Only effective for maps of small size
Methods
Binary trees are recursively defined, so all the methods operating on them are easily defined recursively also.
- Search
- To search for a key
- Compare it with the key at
- If , the value has been found
- If , search the right subtree
- If , search the left subtree
- Insertion
- Search for the key being inserted
- Insert at the leaf reached by the search
- Deletion
- Find the internal node that is follows the key being inserted in an in order traversal (the in order successor)
- Copy key into the in order successor node
- Remove the node copied out of
Performance
- Consider a binary search tree with items and height
- The space used is
- The methods get, put, remove take time
- The height h is in the best case, when the tree is perfectly balanced
- In the worst case, when the tree is basically just a linked list, this decays to
AVL Trees
- AVL trees are balanced binary trees
- For every internal node of the tree, the heights of the subtrees of can differ by at most 1
- The height of an AVL tree storing keys is
- Balance is maintained by rotating nodes every time a new one is inserted/removed
Performance
- The runtime of a single rotation is
- The tree is assured to always have , so the runtime of all methods is
- This makes AVL trees an efficient implementation of binary trees, as their performance does not decay as the tree becomes unbalanced