Transcript Lecture 23

Introduction to C
Programming
CE00312-1
Lecture 23
Binary Trees
Binary Search Tree

A binary tree has a maximum of two branches.

A binary search tree has some further characteristics:

1) With respect to any particular node in the tree, all
those nodes in the left sub-tree have data which are
less (alphabetically for strings) than the node, and all
those in the right sub-tree are greater.
A Binary Search Tree
root of tree
fred
teddy
colin
brian
nick
darryl
fong
thomas
rob
a leaf
Searching a Binary Search
Tree

2) A search for a particular data item, only involves
searching down one branch at each node.

In the example,
searching for “fong” involves
going left at “fred” (“fong” < “fred”),
then right at “colin” (“fong” > “colin”),
then right at “darryl” (“fong” > “darryl”) and
then finding “fong” as a leaf.
Inserting into a Binary Search
Tree
root of tree
fred
teddy
colin
brian
node to
insert
nick
darryl
claude
fong
thomas
rob
a leaf
Insertion into a Binary Search
Tree

3) Insertion of a new node is similar to a search, and
then linking in a new leaf for that node.

In the example, a new node for “claude” would be
inserted to the right of “brian”, because “claude” is less
than both “fred” and “colin” but not “brian”.

4) An Inorder Traversal of the tree yields all the nodes
in order (alphabetical for strings).
Efficiency




Searching, insertion, deletion and sorting (see below)
are efficient because half the tree is eliminated at each
comparison (cf binary search with arrays).
In searching for an item in a binary search tree only
involves going left or right for each node as we descend
the tree. This is similar to choosing first or second half
during a binary search for an array.
Eliminating half the data with each comparison implies
the total number of comparisons is log2 n for n items.
However, this is only guaranteed if the tree is balanced!
A Binary Tree as a Linked List
root
fred
N
U
L
L
darryl
N
U
L
L
teddy
N
U
L
L
nick
N
U
L
L
N
U
L
L
Structure of a tree node
left
left sub-tree
data
right
right sub-tree
Header for Binary Search Tree

Let us define a header file called “tree.h” containing all
our types, structures and tree function prototypes.

This file can be included in all files that need to use
binary search trees.

We shall also keep all our tree functions in “tree.c” and
an application in “treegrow.c”.

All these may be compiled by:
cc treegrow.c tree.c
Header file “tree.h”
#include "stdio.h“ // for I/O and NULL
#include "stdlib.h“ // for malloc
#include "string.h" // for strings
struct node
{
struct node *left;
// left branch
char data[21];
// string data
struct node *right;
// right branch
};
typedef struct node *Treepointer;
// new type called Treepointer
Prototypes for binary search
trees
void inorder(Treepointer);
// traverse tree
void insert(Treepointer, Treepointer);
// insert a node into a tree
Treepointer createnode(char []);
// create a node for an item
Treepointer delete(Treepointer, char []);
// delete an item from a tree
Inorder Traversal



A traversal involves visiting all the nodes in the tree in a
particular sequence.
The most commonly used one is the inorder traversal.
Inorder traversal
1. visits all the nodes to left of the given node,
2. then the given node itself and
3. then visits all those to the right.
For a binary search tree this yields the data in
sort order.
Traversing a binary search tree
root of tree
fred
teddy
colin
brian
nick
darryl
fong
thomas
rob
a leaf
Traversals are recursive

Any function that visits all the nodes in a tree has to be
recursive.

All traversal algorithms should be recursive.

Iterative (using while loops) solutions are extremely
cumbersome - not to mention very difficult - to write.

This should be expected because trees themselves are
recursive data structures - every tree has branches
which are themselves subtrees.
Inorder Traversal
#include "tree.h"
void inorder(Treepointer T)
{
// traverse the tree, T
if (T != NULL)
{
inorder(T -> left); // traverse left
printf("%s\n", T -> data);// print data
inorder(T -> right); // traverse right
} //
else empty tree do nothing
}
To print all nodes in alphabetical order use:
inorder (root);
Algebraic Trees

Inorder Traversal can give the same result for
different trees.

Using the normal infix notation, brackets would have to
be used to distinguish
(A + B) * C
from A + B * C
E.G.
(2 + 3) * 4
2+3*4
20
14
Give
Reverse Polish

However, postorder traversal gives different results
for different trees.

Thus, reverse polish notation can represent algebraic
trees faithfully without the use of either brackets or
operator precedences!
AB+C*
(do
A B + first)
is different from
ABC*+
(do
B C * first)


Hence the use of reverse polish by compilers
Postorder traversal

Postorder traversal is almost the same as inorder
traversal – both have to visit all the same nodes – but in
a different sequence.

The recursive algorithm should be very similar as the two
traversals do similar things.

Only two statements are swapped, so that for a
postorder traversal, the right subtree is visited before
printing the current node, T.
Postorder Traversal
#include "tree.h"
void postorder(Treepointer T)
{
// traverse the tree, T
if (T != NULL)
{
postorder(T -> left); // traverse left
postorder(T -> right);// traverse right
printf("%s ", T -> data);// print data
} //
else empty tree do nothing
}
To print all nodes in reverse polish use:
postorder (root);