Binary Trees – An Introduction
Objectives of this lecture
q Introduce Binary trees and
learn about some of its general operations
q Study a special type of
binary tree called Expression tree.
Introduction to Binary trees
q Linked lists have great
flexibility advantages over arrays, but they have one major weakness – they are
sequential lists.
q In this lecture and the
next, we shall overcome these disadvantages by studying another set of data
structures called binary trees
q A binary tree is either
empty, or it consists of a node called the root together with two binary
trees called the left subtree and the right subtree
q Thus in a binary tree, a
node can have zero, one or at most two branches. The terms parent and child are usually used to
describe the relationship between nodes in a tree. Nodes that do not have any children are called leaves (leaf for single).
q A binary tree with only one
node consists of a root node and empty left and right subtrees. Thus, it has a unique representation.
q However, there are many
representations for a binary tree with more than one node.
q A binary tree with two nodes
can be represented in either of the following ways.
q
q
q q Notice that a child must be
drawn to be either a left or a right child.
i.e. we should never represent a binary tree as follows:
q For the case of a binary
tree with three nodes, one of them must be the root and the remaining will be
distributed among right and left subtrees in one of the following ways:
2+0 1+1 0+2
q Since there are two binary
trees with two nodes, these partitions give rise to the following six possible
representations:
Exercise: Construct all the fourteen binary trees with four nodes.
Traversal of a binary tree
q One of the most important
operations on a binary tree is traversal – visiting each node
q There are many different
ways in which we could traverse a tree.
If we denote the task of visiting the root by V, traversing left subtree by
L and
that of right subtree by R, then we have the following six different traversal methods:
VLR LVR LRV VRL RVL RLV
q By adopting the standard
convention of visiting the left before the right, the above can be reduced to
tree as follows:
VLR
|
LVR
|
LRV
|
Preorder
|
Inorder
|
Postorder
|
Example: Consider the following tree
q Traversal of the above tree
in the three different orders gives:
Preprder: 1 2 3 4 5
Inorder: 1 4 3 5 2
Postorder: 4 5 3 2 1
Expression Tree
q Binary tree has many forms
and applications. One form of binary
tree is the Expression tree which is very important in compiler construction.
q An expression tree is
defined as a binary tree that is built up from arithmetical or logical
expression by placing the operands as the leave nodes and the operators as the
interior nodes.
q For each binary operator,
the left subree consists of its left operand and the right subtree consists of
its right operand.
q For unary operators, one of
the subtrees is empty.
q The following figure shows
some simple expression trees together with a slightly more complicated example
of quadratic formula.
q Notice that the names: preorder, Inorder, and Postorder are actually derived from prefix, infix and postfix expressions respectively.
q The following table shows
the result of traversing these trees in the three different orders.
Implementation of Binary Trees:
q In addition to the three
different traversal operations, others basic operations on binary trees are: CreateTree, ClearTree and EmptyTree. These can be implemented easily using recursion as follows:
typedef
struct treenode TreeNode;
typedef
struct treenode {
TreeEntry
entry;
TreeNode *left;
TreeNode *right;
}
TreeNode;
/* CreateTree: create a tree.
Pre: None.
Post:
An empty binary search tree has been created and root point
s to it.
*/
void
CreateTree(TreeNode **root)
{
*root = NULL;
}
/* TreeEmpty: TRUE if the tree is emtpy.
Pre: The tree to which root points has been
created.
Post:
The function returns the value TRUE or FALSE according as
the tree is
empty or not.
*/
Boolean
TreeEmtpy(TreeNode *root)
{
return root == NULL;
}
/* Preorder: visit each node of the tree in
preorder.
Pre: The binary tree to which root points has
been created.
Post:
The function Visit has been performed on every entry in the
binary tree
in preorder sequence.
*/
void
Preorder(TreeNode *root)
{
if (root) {
Visit(root->entry); //to be defined by
the application
Preorder(root->left);
Preorder(root->right);
}
}
/* Inorder: visit each node of the tree in
inorder.
Pre: The binary tree to which root points has
been created.
Post:
The function Visit has been performed on every entry in the
binary tree
in inorder sequence.
*/
void
Inorder(TreeNode *root)
{
if (root) {
Inorder(root->left);
Visit(root->entry); //to be defined by the application
Inorder(root->right);
}
}
/* Postorder: visit each node of the tree in
postorder.
Pre: The binary tree to which root points has
been created.
Post:
The function Visit has been performed on every entry in the
binary tree
in postorder sequence.
*/
void
Postorder(TreeNode *root)
{
if (root) {
Postorder(root->left);
Postorder(root->right);
Visit(root->entry); //to be defined by the application
}
}
Exercises:
Try Exercises E1-E8
of pages 393-394 of your book.