0% found this document useful (0 votes)
14 views262 pages

09 DS Tree 2024

Uploaded by

meaditya031
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views262 pages

09 DS Tree 2024

Uploaded by

meaditya031
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 262

Tree

And
Its Applications

Alok Kumar Jagadev


Nonlinear Data Structures

n In nonlinear data structures,


n data elements are not organized in a sequential fashion.
n A data item in a nonlinear data structure could be attached to
several other data elements to reflect a special relationship among
them and
n all the data items cannot be traversed in a single run.

n Data structures like multidimensional arrays, trees and graphs


are some examples of widely used nonlinear data structures.
Examples

n A Multidimensional Array is simply a collection of one-dimensional


arrays.

n A Tree is a data structure that is made up of a set of linked nodes,


which can be used to represent a hierarchical relationship among
data elements.

n A Graph is a data structure that is made up of a finite set of edges


and vertices.
n Edges represent connections or relationships among vertices that
stores data elements.
Difference

n Main difference between linear and nonlinear data structures lie in


the way they organize data elements.

n In linear data structures, data elements are organized sequentially


and therefore they are easy to implement in the computer’s
memory.

n In nonlinear data structures, a data element can be attached to


several other data elements to represent specific relationships that
exist among them.
Difficult to Implement

n Due to this nonlinear structure, they might be difficult to implement


in computer’s linear memory compared to implementing linear data
structures.

n Selecting one data structure type over the other should be done
carefully by considering the relationship among the data elements
that needs to be stored.
A Specific Example

n Imagine that a person is hired by company XYZ to organize all of


their records into a computer database.

n The first thing he is asked to do is create a database of names with


all the company's management and employees.

n To start with work, he makes a list of everyone in the company


along with their position and other details.
Employees Table
Disadvantages of Tables

n But this list only shows one view of the company.

n The relationships between management and employees at XYZ


is not represented.

n Also it does not tell which managers are responsible for which
workers and so on.

n Then a tree diagram is a much better structure for showing the


work relationships at XYZ.
Better Representation
Tree Data Structure

n A Tree is a nonlinear data structure that models a hierarchical


organization.

n The characteristic features are that each element may have


several successors (called its “children”) and every element
except one (called the “root”) has a unique predecessor (called its
“parent”).

n Trees are common in computer science: Computer file systems


are trees, the inheritance structure for C++/Java classes is a tree.
What is a Tree ?

n In Computer Science, a tree is an abstract model of a hierarchical


structure

n A tree consists of nodes with a parent-child relation

n Applications:
n Organization Charts
n File Systems
n Programming Environment
Tree Definition

n Here is the recursive definition of an (unordered) tree:

n A tree is a pair (r, S), where r is a node and S is a set of disjoint


trees, none of which contains r.

n The node r is called the root of the tree T, and the elements of the
set S are called its subtrees.

n The set S may be empty.

n The elements of a tree are called its nodes.


Root, Parent and Children
n If T = (r, S) is a tree, then
n r is the root of T and
n S is its set of subtrees S = {T1, T2, T3, . . ., Tn}.
n Each subtree Tj is itself a tree with its own root rj .
n In this case, the node r is called parent of each node rj, and the rj
are called as the children of r.
Basic Terminology
n A node with no children is called a leaf. A node with at least one
child is called an internal node.
n The Node having further sub-branches is called parent node.
n Every node c other than the root is connected by an edge to
some other node p, called the parent of c.
n Also call c a child of p.
An Example

n n1 is the parent of n2 ,n3 and n4,


while n2 is the parent of n5 and
n6. Said another way, n2, n3, and
n4 are children of n1, while n5
and n6 are children of n2.
Connected Tree

n A tree is connected if we start


at any node n other than the
root, move to the parent of n,
to the parent of the parent of n,
and so on, eventually reach the
root of the tree.
n For instance, starting at n7, we
move to its parent, n4, and from
there to n4’s parent, which is
the root, n1.
Ancestors and Descendants

n The parent-child relationship can be extended naturally to


ancestors and descendants.
n Informally, the ancestors of a node are found by following the
unique path from the node to its parent, to its parent’s parent,
and so on.
n The descendant relationship is the inverse of the ancestor
relationship, just as the parent and child relationships are
inverses of each other.
Path and Path Length

n More formally, suppose m1, m2, . . . , mk is a sequence of nodes in


a tree such that m1 is the parent of m2, which is the parent of m3,
and so on, down to mk−1, which is the parent of mk.

n Then m1, m2, . . . , mk is called a path from m1 to mk in the tree.


The path length or length of the path is k −1, one less than the
number of nodes on the path.
Example

n n1, n2, n6 is a path of length 2 from the root n1 to the node n6.
Height and Depth

n In a tree, the height of a node n is the length of a longest path


from n to a leaf. The height of the tree is the height of the root.

n The depth, or level, of a node n is the length of the path from the
root to n.
Example

n node n1 has height 2, n2 has height 1, and leaf n3 has height 0. In


fact, any leaf has height 0. The height of the tree is 2. The depth of
n1 is 0, the depth of n2 is 1, and the depth of n5 is 2.
Level and depth of a binary Tree

Level of binary tree:


The root of the tree has level 0. And the level of any other node is
one more than the level of its parent.

A Level 0

Level 1
B C

D E Level 2

Depth is 3. F G Level 3
Tree Properties

A Property Value
Number of nodes 9
Height 4
B C
Root Node A
Leaves C, D, F, H, I

D E F Interior nodes B, E, G
Ancestors of H A, B, E, G
Descendants of B D, E, F, G, H, I
Siblings of E D, F
G Right subtree of A tree at C

H I
Other Terms
n The size of a tree is the number of nodes it contains.

n The total number of nodes connected to that node is called the


degree of the node.
n Degree of the Tree is nothing but the maximum degree in the tree.
n The nodes with common parent are called siblings.
Siblings
Terminology Explained
Another Example
Subtrees
Traversal Algorithms

n A traversal algorithm signifies visiting or accessing each element in


a data structure systematically.
n Generally, each element is at least visited once.
n It iterates over all the elements of the data structure

n For example, if the operation is to print the contents of the


element, then the traversal would print every element in the
structure.

n The process of applying the operation to an element is called


visiting the element.
Level Order Traversal

n The level order traversal algorithm visits the root, then visits
each element on the first level, then visits each element on the
second level, and so forth, each time visiting all the elements on
one level before going down to the next level.

n If the tree is drawn in the usual manner with its root at the top
and leaves near the bottom, then the level order pattern is the
same as left-to-right top-to-bottom pattern.
Level Order Example
Level order Traversal - Algorithm

n To traverse a nonempty ordered tree:


1. Initialize a queue.
2. Enqueue the root.
3. Repeat steps 4–6 until the queue is empty.
4. Dequeue node x from the queue.
5. Visit x.
6. Enqueue all the children of x in order.
Preorder Traversal

• The preorder traversal of the tree shown above would visit the
nodes in this order: a, b, e, h, i, f, c, d, g, j, k, l, m.
• Note that the preorder traversal of a tree can be obtained by
traversing the tree, beginning at the root and visiting each node the
first time it is encountered on the left.
Preorder Traversal - Algorithm

n To traverse a nonempty ordered tree:


1. Visit the root.
2. Do a recursive preorder traversal of each subtree in order.

n The postorder traversal algorithm does a postorder traversal


recursively to each subtree before visiting the root.
Binary Trees

n A binary tree is either the empty set or a triple T = (r, TL, TR),
where r is a node and TL and TR are disjoint binary trees, neither
of which contains r.

n The node r is called the root of the tree T, and the subtrees TL and
TR are called the left subtree and the right subtree of T rooted at r.
Binary Tree

n A binary tree is a tree in which no node can have more than two
subtrees. In other words, a node can have zero, one or two subtrees.
Five binary trees with three nodes

• If L is the number of leaf nodes in a tree and I is the number of internal


nodes, then L = I + 1.
• If a tree has I internal nodes and N is the total number of nodes, then
the total number of nodes would be equal to N = 2I + 1.
Other Kinds of Binary Trees
(Full Binary Trees)
n Full Binary Tree: A binary tree T is full if each node is either a leaf
or possesses exactly two children.
n The four full binary trees are:
Full Binary Tree
Full Binary Trees

n The full binary tree of height h has l = 2h leaves and m = 2h – 1


internal nodes.

n The full binary tree of height h has a total of n = 2h+1 – 1 nodes.

n The full binary tree with n nodes has height h = lg(n+1) – 1.


Other Kinds of Binary Trees
(Strictly Binary Trees)
§ If every nonleaf node in a binary tree has nonempty left and right
subtrees, the tree is called a strictly binary tree.
§ A strictly binary tree with n leaves always contains 2n -1 nodes.

A
B C

D E

F G
Complete Binary Treetrees)

Complete Binary Tree: A binary tree T in which all levels are fully
filled, except for possibly the last level, which is filled from left to
right.
It’s useful for improving storage optimization because it ensures
that each level is filled entirely before populating the next.

1 1
1 13
1 2 3
2 2 2 3 1
1 4 5 6
4 2 3
2 3
4 5
4 56 7
Complete Binary Tree
Make a Note
n Complete binary trees are important because they have a simple
and natural implementation using ordinary arrays.

n The natural mapping is actually defined for any binary tree:


n Assign the number 1 to the root; for any node, if i is its number,
n then assign 2i to its left child and
n 2i+1 to its right child (if they exist).

n This assigns a unique positive integer to each node. Then simply


store the element at node i in t[i], where t[] is an array.
Binary Tree Representations
n If a complete binary tree with n nodes (depth = log n + 1) is
represented sequentially, then for any node with index i, 1 ≤ i ≤ n,
we have:
n parent(i) is at i/2 if i≠1. If i=1, i is at the root and has no parent.
n leftChild(i) is at 2i if 2i ≤ n. If 2i > n, then i has noleft child.
n rightChild(i) is at 2i+1 if 2i +1 ≤ n. If 2i +1 >n,
then i has no right child.
Array Implementation
Array Representation Trees

n A complete binary tree can be represented by an array t of the


same length as the number of nodes
n t[k] is identified with node
n That is, t[k] holds the data of node k
n Advantage:
n no need to store left and right pointers in the nodes → save
memory
n Direct access to nodes: to get to node k, access t[k]
The Disadvantage

n Figure above shows the incomplete binary tree and the natural mapping
of its nodes into an array which leaves some gaps.
Illustration of Array Representation

15
8 20

2 11 30 27

6 18 12
13

15 8 20 2 11 30 27 13 6 18 12
0 1 2 3 4 5 6 7 8 9 10

n Notice: Left child of t[4] (of data 11) is t[2*4+1]=T[9] (of data 18), and
its right child is t[2*4+2]=T[10] (of data 12).

n Parent of t[3] is t[(3-1)/2]=t[1], and parent of t[4]=t[(4-1)/2]=t[1]


Array Implementation
n Advantages
n Direct Access
n Finding the Parent / Children is fast

n Disadvantages
n Wastage of memory
n Insertion and Deletion will be costlier
n Array size and depth
Linked List Representation of Binary
Tree
n The most popular and practical way of representing a binary tree is
using linked list (or pointers). In linked list, every element is represented
as nodes. A node consists of three fields such as :
n (a) Left Child (LChild)
n (b) Information of the Node (Info)
n (c) Right Child (RChild)
n The LChild links points to the left child of the node, Info holds the
information of the node and the RChild holds the address of right child
node of the node. The structure of a binary tree node is shown below:
Binary Tree Representations (Linked
List)

If a node has no left or / and right node, corresponding LChild or RChild is


assigned to NULL
Linked List Implementation
Binary Tree ADT

n The Binary Tree ADT extends the Tree ADT, i.e., it inherits all the
methods of the Tree ADT, in addition to that it supports the
following additional accessor methods:
n position left(p): return the left child of p, an error condition
occurs if p has no left child.
n position right(p): return the right child of p, an error condition
occurs if p has no right child.
n boolean hasLeft(p): test whether p has a left child
n boolean hasRight(p): test whether p has a right child
Linked List Implementation

n Advantages
n No wastage of memory
n Insertion and Deletion will be easy

n Disadvantages
n Does not provide direct access
n Additional space in each node.
Binary Tree Traversal

n Traversal is the process of visiting every node once

n The three traversal algorithms that are used for general trees
apply to binary trees as well: the preorder traversal, the
postorder traversal, and the level order traversal.

n In addition, binary trees support a fourth traversal algorithm:


the inorder traversal.
Level Order Traversal

n To traverse a nonempty binary tree:

1. Initialize a queue.
2. Enqueue the root.
3. Repeat steps 4–7 until the queue is empty.
4. Dequeue a node x from the queue.
5. Visit x.
6. Enqueue the left child of x if it exists.
7. Enqueue the right child of x if it exists.
Level Order
Preorder Traversal

n To traverse a nonempty binary tree:

1. Visit the root.


2. If the left subtree is nonempty, do a preorder traversal on it.
3. If the right subtree is nonempty, do a preorder traversal on it.
Preorder
Postorder Traversal

n To traverse a nonempty binary tree:


1. If the left subtree is nonempty, do a postorder traversal on it.
2. If the right subtree is nonempty, do a postorder traversal on it.
3. Visit the root.
Postorder
Inorder Traversal

n To traverse a nonempty binary tree:


1. If the left subtree is nonempty, do a preorder traversal on it.
2. Visit the root.
3. If the right subtree is nonempty, do a preorder traversal on it.
Inorder
Preoder, Inorder, Postorder

In Preorder, the root is visited


n
before traversals of both the
Preorder Traversal:
subtrees. 1. Visit the root
2. Traverse left subtree
n In Inorder, the root is visited 3. Traverse right subtree
in-between left and right
subtree traversals.
Inorder Traversal:
n In Postorder, the root is visited 1. Traverse left subtree
after the traversals of both 2. Visit the root
subtrees. 3. Traverse right subtree

Postorder Traversal:
1. Traverse left subtree
2. Traverse right subtree
3. Visit the root
Illustrations for Traversals

n Assume: visiting a node is printing 1


its node number
3 7

n Preorder: 1 3 5 4 6 7 8 9 10 11 12
5 8 9
n Inorder: 4 5 6 3 1 8 7 9 11 10 12
Postorder: 4 6 5 3 8 11 12 10 9 7 1 4 10
n 6

11 12
Illustrations for Traversals (Contd.)

15
8 20

2 11 27

6 10 12 22 30

3 7 14
Illustrations for Traversals (Contd.)

Assume: visiting a node is printing its data 15


n Preorder: 15 8 2 6 3 7 11 10 12 14 20 27 22 30 8 20
n Inorder: 2 3 6 7 8 10 11 12 14 15 20 22 27 30
2 11 27
n Postorder: 3 7 6 2 10 14 12 11 8 22 30 27 20 15

6 10 12 22 30

3 7 14
Code for the Traversal Techniques
void preOrder(Tree *root){
if (root == NULL) return;
visit(root->info);
n The code for visit depends on
preOrder(root->left);
the application
preOrder(root-> right);
n A typical example for visit(…) is }
to print out the data part of its void inOrder(Tree *root){
input node if (root == NULL) return;
inOrder(root-> left);
visit(root->info);
typedef struct node { inOrder(root-> right);
int info; }
struct node *left; void postOrder(Tree *root){
struct node *right; if (root == NULL) return;
} Tree; postOrder(root-> left);
postOrder(root->right));
visit(root->info);
}
A
B C Code for the Traversal Techniques
void preOrder(Tree *root) {
void preOrder(Tree *root) {
if (root == NULL) return;
if (root == NULL) return;
visit(root->info);
visit(root->info);
preOrder(root->left);
preOrder(root->left);
preOrder(root-> right);
preOrder(root-> right);
}
}
void preOrder(Tree *root) {
void preOrder(Tree *root) {
if (root == NULL) return;
if (root == NULL) return;
visit(root->info);
visit(root->info);
preOrder(root->left);
preOrder(root->left);
preOrder(root-> right);
preOrder(root-> right);
}
}
void preOrder(Tree *root) {
void preOrder(Tree *root) {
if (root == NULL) return;
if (root == NULL) return;
visit(root->info);
visit(root->info);
preOrder(root->left);
preOrder(root->left);
preOrder(root-> right);
preOrder(root-> right);
}
}
void preOrder(Tree *root) {
void preOrder(Tree *root) {
if (root == NULL) return;
if (root == NULL) return;
visit(root->info);
visit(root->info);
preOrder(root->left);
preOrder(root->left);
preOrder(root-> right);
preOrder(root-> right);
}
}
A
B C Code for the Traversal Techniques
void inOrder(Tree *root) {
void inOrder(Tree *root) {
if (root == NULL) return;
if (root == NULL) return;
inOrder(root->left);
inOrder(root->left);
visit(root->info);
visit(root->info);
inOrder(root-> right);
inOrder(root-> right);
}
}
void inOrder(Tree *root) {
void inOrder(Tree *root) {
if (root == NULL) return;
if (root == NULL) return;
inOrder(root->left);
inOrder(root->left);
visit(root->info);
visit(root->info);
inOrder(root-> right);
inOrder(root-> right);
}
}
void inOrder(Tree *root) {
void inOrder(Tree *root) {
if (root == NULL) return;
if (root == NULL) return;
inOrder(root->left);
inOrder(root->left);
visit(root->info);
visit(root->info);
inOrder(root-> right);
inOrder(root-> right);
}
}
void inOrder(Tree *root) {
void inOrder(Tree *root) {
if (root == NULL) return;
if (root == NULL) return;
inOrder(root->left);
inOrder(root->left);
visit(root->info);
visit(root->info);
inOrder(root-> right);
inOrder(root-> right);
}
}
A
B C Code for the Traversal Techniques
void postOrder(Tree *root) {
void postOrder(Tree *root) { if (root == NULL) return;
if (root == NULL) return; postOrder(root->left);
postOrder(root->left); postOrder(root-> right);
postOrder(root-> right); visit(root->info);
visit(root->info); }
} void postOrder(Tree *root) {
void postOrder(Tree *root) { if (root == NULL) return;
if (root == NULL) return; postOrder(root->left);
postOrder(root->left); postOrder(root-> right);
postOrder(root-> right); visit(root->info);
visit(root->info); }
} void postOrder(Tree *root) {
void postOrder(Tree *root) { if (root == NULL) return;
if (root == NULL) return; postOrder(root->left);
postOrder(root->left); postOrder(root-> right);
postOrder(root-> right); visit(root->info);
visit(root->info); }
} void postOrder(Tree *root) {
void postOrder(Tree *root) { if (root == NULL) return;
if (root == NULL) return; postOrder(root->left);
postOrder(root->left); postOrder(root-> right);
postOrder(root-> right); visit(root->info);
visit(root->info); }
}
Nonrecursive Preorder Traversal:
General Algorithm

curr = root; //traversal starts at root node


push(curr)
while(stack is nonempty)
curr=pop()
print(curr->info)
if(curr->right ≠ NULL)
push(curr->right)
if(curr->left ≠ NULL)
push(curr->left)
Nonrecursive Inorder Traversal:
General Algorithm
curr = root; //start traversing the binary tree at the root node
while(curr ≠ NULL or stack is nonempty)
if(curr ≠ NULL)
push(curr)
curr = curr->left
else
curr = pop()
print(curr->info) //visit the node
curr = curr->right
//move to the right child
Nonrecursive Postorder Traversal:
General Algorithm
curr = root; //start traversal at root node
while(curr!=NULL or stack is not empty)
while (curr != NULL)
if(curr->right != NULL)
push(curr->right)
push(curr)
curr = curr->left
curr=pop()
if(curr->right ≠ NULL and top() == curr->right)
pop()
push(curr)
curr = curr->right
else
print(curr->info)
curr = NULL
Binary Tree Construction

n Suppose that the elements in a binary tree are distinct.


n Can you construct the binary tree from which a given traversal
sequence obtained?
n When a traversal sequence has more than one element, the binary
tree is not uniquely defined.
n Therefore, the tree from which the sequence was obtained cannot
be reconstructed uniquely.
Some Examples

a a
preorder = ab
b b

inorder = ab b a

a b

postorder = ab b b

a a
Binary Tree Construction

n Can you construct the binary tree, given two traversal


sequences?
n Depends on which two sequences are given.
Preorder And Postorder

preorder = ab a a

postorder = ba b b

§ Preorder and postorder do not uniquely define a binary tree.


Preorder And Postorder

preorder = abc a a

postorder = bca b b c
c

If the tree is full the Preorder and postorder uniquely define a binary tree.
Preorder And Postorder

preorder = 1, 2, 4, 8, 9, 5, 3, 6, 7
postorder = 8, 9, 4, 5, 2, 6, 7, 3, 1

If the tree is full then unique tree is constructed

§ the leftmost element in preorder sequence is root of tree


§ Since the tree is full and array size is more than 1.
§ The value next to 1 in preorder, must be left child of root.
§ So we know 1 is root and 2 is left child. How to find the all nodes in
left subtree?
§ 2 is root of all nodes in left subtree. All nodes before 2 in postorder
must be in left subtree. Now we know 1 is root, elements {8, 9, 4, 5,
2} are in left subtree, and the elements {6, 7, 3} are in right subtree.
Preorder And Postorder

preorder = 1, 2, 4, 8, 9, 5, 3, 6, 7
postorder = 8, 9, 4, 5, 2, 6, 7, 3, 1

If the tree is full then unique tree is constructed

1 1
/ \ / \
/ \ 2 3
{8, 9, 4, 5, 2} {6, 7, 3} / \ / \
4 5 6 7
/\
8 9
Inorder And Preorder

n inorder: g d h b e i a f j c

n preorder: a b d g h e i c f j

n Scan the preorder left to right using the inorder to separate left
and right subtrees.

n a is the root of the tree: gdhbei are nodes in the left subtree: fjc
are nodes in the right subtree.

gdhbei fjc
Inorder And Preorder

gdhbei fjc

n preorder: b d g h e i c f j
n b is the next root; gdh are in the left subtree; ei are in the right subtree.
a

b fjc

gdh ei
Inorder And Preorder

b fjc n preorder: d g h e i c f j
gdh ei n d is the next root; g is in the left
subtree; h is in the right subtree.

a
b fjc

d ei
g h
Inorder And Postorder

n Scan postorder from right to left using inorder to separate left


and right subtrees.

n inorder: g d h b e i a f j c

n postorder: g h d i e b j f c a

n Tree root is a; gdhbei are in left subtree; fjc are in right


subtree.
Construction of No. of Trees

Catalan Number: T(n) = (2*n)! / [(n+1)! n!]


§ # of Unlabeled Binary Tree: T(n) = (2*n)! / [(n+1)! n!]
§ # of Labelled Binary Tree: Every unlabeled tree with n nodes can create n!
labeled trees by assigning different permutations of labels to all nodes. So,
T(n) = [ (2*n ) ! / (n+1) ! * n ! ] * n !
Count Leaf nodes in a Binary Trees

struct node {
int info;
struct node* left;
struct node* right;
};

/* Function to count of leaf nodes in a binary tree*/


unsigned int leafCount(struct node* root) {
if(root == NULL) return 0;
if(root->left == NULL && root->right == NULL)
return 1;
else
return leafCount(root->left)+ leafCount(root->right);
}
A
B C
Count Leaf nodes in a Binary Trees
int lCount(struct node* root) {
int lCount(struct node* root) { if(root == NULL) return 0;
if(root == NULL) return 0; if(root->left == NULL && root-
if(root->left == NULL && root->right == NULL) >right == NULL)
return 1; return 1;
else else
return lCount(root->left)+ lCount(root->right); return lCount(root->left)+
lCount(root->right);
}
}
int lCount(struct node* root) { int lCount(struct node* root) {
if(root == NULL) return 0; if(root == NULL) return 0;
if(root->left == NULL && root->right == NULL) if(root->left == NULL && root-
>right == NULL)
return 1;
return 1;
else
else
return lCount(root->left)+ lCount(root->right);
return lCount(root->left)+
}
lCount(root->right);
}
Count non Leaf nodes in a Binary Trees

int countNonleaf(struct node* root) {


if (root == NULL || (root->left == NULL && root->right == NULL))
return 0;
return 1 + countNonleaf(root->left) + countNonleaf(root->right);
}
A
B C Count non Leaf nodes in a Binary Trees
int countNonleaf(struct node* root) {
if (root == NULL || (root->left == NULL && root->right == NULL))
return 0;
return 1 + countNonleaf(root->left) + countNonleaf(root->right);
}
int countNonleaf(struct node* root) {
if (root == NULL || (root->left == NULL && root->right == NULL))
return 0;
return 1 + countNonleaf(root->left) + countNonleaf(root->right);
}
int countNonleaf(struct node* root) {
if (root == NULL || (root->left == NULL && root->right == NULL))
return 0;
return 1 + countNonleaf(root->left) + countNonleaf(root->right);
}
int countNonleaf(struct node* root) {
if (root == NULL || (root->left == NULL && root->right == NULL))
return 0;
return 1 + countNonleaf(root->left) + countNonleaf(root->right);
}
Count total nodes in a Binary Trees

unsigned int countNodes(struct node *root) {


if (root == NULL)
return 0;
else
return 1+ countNodes(root->left) + countNodes(root->right);
}
A
B C Count total nodes in a Binary Trees
unsigned int countNodes(struct node *root) {
if (root == NULL)
return 0;
else
unsigned int countNodes(struct node *root) { return 1+ countNodes(root->left) +
if (root == NULL) countNodes(root->right);
return 0; }
else
return 1+ countNodes(root->left) + unsigned int countNodes(struct node *root) {
countNodes(root->right); if (root == NULL)
} return 0;
else
return 1+ countNodes(root->left) +
unsigned int countNodes(struct node *root) { countNodes(root->right);
if (root == NULL) }
return 0; unsigned int countNodes(struct node *root) {
else if (root == NULL)
return 1+ countNodes(root->left) + return 0;
countNodes(root->right); else
} return 1+ countNodes(root->left) +
countNodes(root->right);
}
MCQ-1
Which of the following is a true about Binary Trees

(A) Every binary tree is either complete or full.


(B) Every complete binary tree is also a full binary tree.
(C) Every full binary tree is also a complete binary tree.
(D) No binary tree is both complete and full.
(E) None of the above
MCQ-1 A) is incorrect. For example,
the following Binary tree is
Which of the following is a true about Binary Trees neither complete nor full
(A) Every binary tree is either complete or full. 12
(B) Every complete binary tree is also a full binary tree. /
(C) Every full binary tree is also a complete binary tree. 20
(D) No binary tree is both complete and full. /
(E) None of the above 30

Answer: (E) B) is incorrect. The following


• Explanation: A full binary tree (sometimes proper binary tree is complete but
binary tree or 2-tree or strictly binary tree) is a tree not full
in which every node other than the leaves has two 12
children. / \
• A complete binary tree is a binary tree in which every 20 30
level, except possibly the last, is completely filled, /
and all nodes are as far left as possible.
30
MCQ-1 C) is incorrect. Following
Binary tree is full, but not
complete
Which of the following is a true about Binary Trees
(A) Every binary tree is either complete or full. 12
(B) Every complete binary tree is also a full binary tree. / \
(C) Every full binary tree is also a complete binary tree. 20 30
(D) No binary tree is both complete and full. / \
(E) None of the above 20 40
D) is incorrect. Following
Answer: (E) Binary tree is both complete
and full

12
/ \
20 30
/ \
10 40
MCQ-2
Suppose the level of root is 1 and levels of left and right children of root is 2.
The maximum number of nodes on level i of a binary tree is

(A) 2i-1
(B) 2i
(C) 2i+1
(D) 2(i+1)/2
(E) None of the above
MCQ-2
Suppose the level of root is 1 and levels of left and right children of root is 2.
The maximum number of nodes on level i of a binary tree is

(A) 2i-1
(B) 2i
(C) 2i+1
(D) 2(i+1)/2
(E) None of the above

Answer: (A)

Explanation: Number of nodes of binary tree will be maximum only when tree
is full complete, therefore answer is 2i-1
So, option (A) is true.
MCQ-3
In a complete k-ary tree, every internal node has exactly k children or no child.
What is the number of leaf nodes in such a tree with n internal nodes?
(A) nk
(B) (n – 1) k+ 1
(C) n( k – 1) + 1
(D) n(k – 1)
(E) None of the above
where L is the number of leaf nodes
MCQ-3 and n is the number of internal nodes.
since it is a complete k tree, so every
internal node will have k children.
In a complete k-ary tree, every internal Total children = n*k
node has exactly k children or no child. Total nodes = n*k + 1
What is the number of leaf nodes in such
Leaf nodes = n*k+1-n = (k-1)*n+1
a tree with n internal nodes?
Example:
(A) nk
o
(B) (n – 1) k+ 1
/ | \
(C) n(k – 1) + 1
o o o
(D) n(k – 1)
/|\ /|\ /|\
(E) None of the above
o o oo o oo oo

Answer: (C)
k=3
Explanation: For an k-ary tree where each
node has k children or no child, following Number of internal nodes n = 4
relation holds Number of leaf nodes = (k-1)*n + 1
L = (k-1)*n + 1 = (3-1)*4 + 1 = 9
MCQ-4
The maximum number of binary trees that can be formed with three unlabeled
nodes is:

(A) 1
(B) 5
(C) 4
(D) 3
(E) None of the above
Note that nodes are
unlabeled. If the nodes
MCQ-4 are labeled, we get
more number of trees.
We can find the
The maximum number of binary
O O number of binary tree
trees that can be formed with
/ \ by Catalan number
three unlabeled nodes is:
number:
(A) 1 O O
Here n = 3
(B) 5 / \
Number of binary tree
(C) 4 O O
= (2nCn)/ (n+1)
(D) 3 (ii) (iv)
= (2*3C3)/ (3+1)
(E) None of the above = 5.
Answer: (B) O O
So, option (B) is
Explanation: Following are all / \ correct.
possible unlabeled binary tree O O The first few Catalan
O \ / numbers for n = 0, 1,
/ \ O O 2, 3, … are 1, 1, 2, 5,
O O (iii) (v) 14, 42, 132, 429, 1430,
4862, …
(i)
MCQ-5
The number of leaf nodes in a rooted tree of n nodes, with each node having 0
or 3 children is:
(A) n/2
(B) (n-1)/3
(C) (n-1)/2
(D) (2n+1)/3
(E) None of the above
MCQ-5
What is the number of leaf nodes in a rooted tree of n nodes, with each node
having 0 or 3 children?
(A) n/2
(B) (n-1)/3
(C) (n-1)/2
(D) (2n+1)/3
(E) None of the above
Answer: (D)

Explanation: Let L be the number of leaf nodes and I be the number of internal
nodes, then following relation holds for above given tree
L = (3-1)I + 1 = 2I + 1
Total number of nodes(n) is sum of leaf nodes and internal nodes
n = L + I => I = n - L Putting the value of I in the above equation
We get L = (2n+1)/3
MCQ-6
A complete n-ary tree is a tree in which each node has n children or no
children. Let I be the number of internal nodes and L be the number of leaves
in a complete n-ary tree. If L = 41, and I = 10, what is the value of n?
(A) 6
(B) 3
(C) 4
(D) 5
(E) None of the above
MCQ-6
A complete n-ary tree is a tree in which Explanation: For an n-ary tree where
each node has n children or no children. each node has n children or no children,
Let I be the number of internal nodes and following relation holds
L be the number of leaves in a complete L = (n-1)*I + 1
n-ary tree. If L = 41, and I = 10, what is
Where L is the number of leaf nodes and
the value of n?
I is the number of internal nodes.
(A) 6
(B) 3
Let us find out the value of n for the
(C) 4 given data.
(D) 5
(E) None of the above L = 41 , I = 10
41 = 10*(n-1) + 1
Answer: (D) (n-1) = 4
n=5
MCQ-7
A scheme for storing binary trees in an array X is as follows. Indexing of X
starts at 1 instead of 0. the root is stored at X[1]. For a node stored at X[i], the
left child, if any, is stored in X[2i] and the right child, if any, in X[2i+1]. To be
able to store any binary tree on n nodes the minimum size of X should be.

(A) log2n
(B) n
(C) 2n + 1
(D) 2^n — 1
(E) None of the above
MCQ-7
A scheme for storing binary trees in an Explanation: For a right skewed binary
array X is as follows. Indexing of X tree, number of nodes will be 2n – 1. For
starts at 1 instead of 0. the root is example, in below binary tree, node ‘A’
stored at X[1]. For a node stored at X[i], will be stored at index 1, ‘B’ at index 3,
the left child, if any, is stored in X[2i] ‘C’ at index 7 and ‘D’ at index 15.
and the right child, if any, in X[2i+1].
To be able to store any binary tree on n A
nodes the minimum size of X should be. \
\
(A) log2n B
(B) n \
(C) 2n + 1 \
(D) 2n - 1 C
(E) None of the above \
\
Answer: (D) D
MCQ-8
Consider the following nested representation of binary trees: (X Y Z) indicates Y
and Z are the left and right sub stress, respectively, of node X. Note that Y and Z
may be NULL, or further nested. Which of the following represents a valid binary
tree?
(A) (1 2 (4 5 6 7))
(B) (1 (2 3 4) 5 6) 7)
(C) (1 (2 3 4)(5 6 7))
(D) (1 (2 3 NULL) (4 5))
(E) None of the above
MCQ-8
Explanation: C is fine.
Consider the following nested
representation of binary trees: (X Y Z) (1 (2 3 4)(5 6 7)) represents following
indicates Y and Z are the left and right binary tree
sub stress, respectively, of node X.
Note that Y and Z may be NULL, or 1
further nested. Which of the following / \
represents a valid binary tree?
2 5
(A) (1 2 (4 5 6 7))
/\ /\
(B) (1 (2 3 4) 5 6) 7)
3 4 6 7
(C) (1 (2 3 4)(5 6 7))
A) (1 2 (4 5 6 7)) is not fine as there are 4
(D) (1 (2 3 NULL) (4 5)) elements in one bracket.
(E) None of the above B) (1 (2 3 4) 5 6) 7) is not fine as there are
2 opening brackets and 3 closing.
Answer: (C) D) (1 (2 3 NULL) (4 5)) is not fine one
bracket has only two entries (4 5)
MCQ-9
Consider a node X in a Binary Tree. Given that X has two children, let Y be
Inorder successor of X. Which of the following is true about Y?
(A) Y has no right child
(B) Y has no left child
(C) Y has both children
(D) None of the above
(E) None of the above
MCQ-9
Consider a node X in a Binary Tree. Given that X has two children, let Y be
Inorder successor of X. Which of the following is true about Y?
(A) Y has no right child
(B) Y has no left child
(C) Y has both children
(D) None of the above
(E) None of the above

Answer: (B)

Explanation: Since X has both children, Y must be leftmost node in right


child of X.
MCQ-10
The height of a tree is the length of the longest root-to-leaf path in it. The
maximum and minimum number of nodes in a binary tree of height 5 are
(A) 63 and 6, respectively
(B) 64 and 5, respectively
(C) 32 and 6, respectively
(D) 31 and 5, respectively
(E) None of the above
MCQ-10
The height of a tree is the length of the longest root-to-leaf path in it. The
maximum and minimum number of nodes in a binary tree of height 5 are
(A) 63 and 6, respectively
(B) 64 and 5, respectively
(C) 32 and 6, respectively
(D) 31 and 5, respectively
(E) None of the above

Answer: (A)
Explanation:
Number of nodes is maximum for a perfect binary tree.
A perfect binary tree of height h has 2h+1 - 1 nodes

Number of nodes is minimum for a skewed binary tree.


A perfect binary tree of height h has h+1 nodes.
MCQ-11
A binary tree T has 20 leaves. The number of nodes in T having two
children is
(A) 18
(B) 19
(C) 17
(D) Any number between 10 and 20
(E) None of the above
MCQ-11
A binary tree T has 20 leaves. The number Putting values of above terms,
of nodes in T having two children is
(A) 18 L + (I-1)*(k+1) + k = 2 * (L + I - 1)
(B) 19 L + k*I - k + I -1 + k = 2*L + 2I - 2
(C) 17 L + K*I + I - 1 = 2*L + 2*I - 2
(D) Any number between 10 and 20 K*I + 1 - I = L
(E) None of the above (K-1)*I + 1 = L

Answer: (B) Given k = 2, L=20


Explanation: ==> (2-1)*I + 1 = 20
Sum of all degrees = 2 * |E|. ==> I = 19
Here considering tree as a k-ary tree : ==> T has 19 internal nodes which are
Sum of degrees of leaves + Sum of having two children.
degrees for Internal Node except root +
Root's degree = 2 * (No. of nodes - 1).
Expression Trees
A Binary Expression Tree

A special kind of binary tree in which:


1. Each leaf node contains a single operand
2. Each nonleaf node contains a single binary operator
3. The left and right subtrees of an operator node represent
subexpressions that must be evaluated before applying the operator at
the root of the subtree.
A Four-Level Binary Expression

- /

8 5 + 3

4 2
Levels Indicate Precedence

§ The levels of the nodes in the tree indicate their relative precedence
of evaluation (Do not need parentheses to indicate precedence).

§ Operations at deeper levels of the tree are evaluated first than those
upper.

§ The operation at the root is always the last operation to be performed.


A Binary Expression Tree
*

+ 3

4 2

What value does it have?

( 4 + 2 ) * 3 = 18
Expression Tree Examples

Inorder Traversal Result Expression Tree Expression


+
a+3 (a+3)
a 3

+
3 -
3+4*5-9+6 3+(4*5-(9+6))
* +
4 5 9 6
log
log x log(x)
x

!
n! n!
n
Why Expression trees?

n Expression trees are used to remove ambiguity in expressions.


n Consider the algebraic expression 2 - 3 * 4 + 5.
n Without the use of precedence rules or parentheses, different
orders of evaluation are possible:
((2-3)*(4+5)) = -9
((2-(3*4))+5) = -5
(2-((3*4)+5)) = -15
(((2-3)*4)+5) = 1
(2-(3*(4+5))) = -25

n The expression is ambiguous because it uses infix notation:


each operator is placed between its operands.
Why Expression trees? (contd.)

n Storing a fully parenthesized expression, such as ((x+2)-(y*(4-


z))), is wasteful, since the parentheses in the expression need to
be stored to properly evaluate the expression.
n A compiler will read an expression in a language, and transform it
into an expression tree.
n Expression trees impose a hierarchy on the operations in the
expression.
n Terms deeper in the tree get evaluated first.
n This allows the establishment of the correct precedence of operations
without using parentheses.
Why Expression trees? (contd.)

n Expression trees can be very useful for:


n Evaluation of the expression.
n Generating correct compiler code to actually compute the
expression's value at execution time.
n Performing symbolic mathematical operations (such as
differentiation) on the expression.
Evaluating an Expression tree
Assuming that t is a valid expression tree, a pseudo code algorithm for
evaluating the expression tree is:

evalExpr(ExpressionTree t){
if(t->left == NULL && t->right == NULL) // node t is a leaf node
return (t->info) // which is an operand
else {
op = t->info
opnd1 = evalExpr(t->left)
opnd2 = evalExpr(t->right) ;
return(eval(opnd1, op, opnd2))
}
} +

2 * Order of evaluation: 3 1 2
(2 + ((5 – 1) * 3))
- 3

5 1
Evaluating an Expression tree
evalExpr(ExpressionTree t){
+
if(t->left==NULL && t->right==NULL)
2 * return (t->info)
else {
- 3
op = t->info
5 1 opnd1 = evalExpr(t->left)
evalExpr(ExpressionTree t){
opnd2 = evalExpr(t->right) ;
if(t->left==NULL && t->right==NULL)
return(eval(opnd1, op, opnd2)) }
return (t->info)
}
else {
op = t->info evalExpr(ExpressionTree t){
opnd1 = evalExpr(t->left) if(t->left==NULL && t->right==NULL)
opnd2 = evalExpr(t->right) ; return (t->info)
return(eval(opnd1, op, opnd2)) } else {
} op = t->info
opnd1 = evalExpr(t->left)
evalExpr(ExpressionTree t){ opnd2 = evalExpr(t->right) ;
if(t->left==NULL && t->right==NULL) return(eval(opnd1, op, opnd2)) }
return (t->info) }
else { ... }
evalExpr(ExpressionTree t){
}
if(t->left==NULL && t->right==NULL)
return (t->info)
else { ... }
}
Constructing an expression tree from a
postfix expression
n The pseudo code algorithm to convert a valid postfix expression,
containing binary operators, to an expression tree:

while(not the end of the expression) {


if(symbol == operand) {
create a node for the operand (named node)
push(node)
}
if(symbol == operator) {
create a node for the operator (named node)
node->right = pop()
node->left=pop()
push(node)
}
}
Easy to generate the infix, prefix,
postfix expressions (how?)
*

- /

8 5 + 3

4 2

Infix: ((8-5)*((4+2)/3))
Prefix: *-85 /+423
Postfix: 85- 42+3/*
Inorder Traversal: (A + H) / (M - Y)
Print second
tree

+ -

A H M Y

Print left subtree first Print right subtree last


Preorder Traversal: / + A H - M Y
Print first
tree

+ -

A H M Y

Print left subtree second Print right subtree last


Postorder Traversal: A H + M Y - /
Print last
tree

+ -

A H M Y

Print left subtree first Print right subtree second


Binary Search Trees
n Binary search tree
n Every element has a unique key.
n The keys in a nonempty left subtree (right subtree) are smaller
(larger) than the key in the root of subtree.
n The left and right subtrees are also binary search trees.
Binary Search Trees
§ Binary Search Trees (BST) are a type of Binary Trees with a
special organization of data.
§ This data organization leads to O(log n) complexity for
searching, insertion and deletion in certain types of the BST
(balanced trees).
n O(h) in general
Binary Search Algorithm

Binary Search algorithm of an array of sorted items reduces the


search space by one half after each comparison

34 41 56 63 72 89 95
0 1 2 3 4 5 6

34 41 56 72 89 95
0 1 2 4 5 6

72 95
34 56
0 2 4 6
Organization Rule for BST

• values at all nodes in the left subtree of a node are less than
the node value
• values in all nodes at the right subtree of a node are greater
than the node values
63

41 89

34 56 72 95
Binary Tree

typedef struct node {


int info;
struct node *left;
struct node *right
} *treeNode;
BST Operations: Search

Searching in the BST


method search(key)
• implements the binary search based on comparison of the items in
the tree
• the items in the BST must be comparable (e.g integers, strings, etc.)

§ The search starts from the root node.


§ It probes down, comparing the values in each node with the target,
till it finds the node value equal to the target.
§ Returns this node address or null if there is none (i.e. search is
unsuccessful).
Search in a BST: Non-Recursive code

treeNode iterativeSearch(treeNode root, int key) {


// Traverse untill root reaches to terminal node
while (root != NULL) {
if (key > root->info) // pass right subtree as new tree
root = root->right;
else if (key < root->info) // pass left subtree as new tree
root = root->left;
else
return root; // if the key is found return 1
}
return NULL;
}
Search in a BST: Recursive code
treeNode search(treeNode root, int key) {
// Base Cases: root is null or key is present at root
if (root == NULL || root->info == key)
return root;

// Key is greater than root's key


if (root->info < key)
return search(root->right, key);

// Key is smaller than root's key


return search(root->left, key);
}
BST Operations: Insertion

method insert(key)
n find the place for the new item near the frontier of the BST while
retaining its organization of data:
n starting at the root it probes down the tree till it finds a node whose left
or right pointer is NULL and that is a logical place for the new value to
be inserted
Operations:: Insertion
Case 1: The Tree is Empty
• Set the root to a new node containing the item
Case 2: The Tree is Not Empty
• Call a recursive function to insert the item

10
10 > 7
7

10 > 9
5 9

4 6 8 10
BST Insertion: Pseudocode

if tree is empty
create a root node with the new key
else
if key = node->info
// replace the node with the new value (unique node values)
else if key > node->info // compare key with the right subtree
if the right subtree is empty create a leaf node
add key in right subtree
else if key < node->info // compare key with the left subtree
if the left subtree is empty create a leaf node
add key to the left subtree
BST Insertion: Nonrecursive Code

void insert (treeNode root, int key) { treeNode findPos(treeNode root, int
treeNode newNode, parent; key) {
newNode=(treeNode) malloc(sizeof(struct node)); treeNode curr=root;
newNode->info = key; while (root != NULL) {
newNode->left = newNode->right = NULL; curr=root;
if(root==NULL) { if (key > root->info)
root = newNode; root=root->right;
else if (key < root->info)
return;
root=root->left;
}
else return root;
parent = findPos(root, key);
}
if(key<parent->info) return curr;
parent->left=newNode; }
else if (key>parent->info)
parent->right = newNode;
return;
}
BST Insertion: Nonrecursive Code

treeNode insert (treeNode root, int key) {


treeNode newNode, curr, parent;
newNode = (treeNode) malloc(sizeof(struct node));
if (root == NULL {
root=newnode;
return;
}
curr=root;
parent=NULL;
while (curr != NULL) {
parent=curr;
if (key < curr->info) curr = curr->left;
else curr = curr->right;
}
if (key < parent->info) parent->left = newnode;
else parent->right = newnode;
return;
}
BST Insertion: Recursive

treeNode insert(treeNode root, int key) {


if(root==NULL) {
root=(treeNode) malloc(sizeof(struct node));
root->left=root->right = NULL;
root->info=key;
}
else {
if(key<root->info)
root->left=insert(root->left, key);
else if(key>root->info)
root->right=insert(root->right, key);
}
return root;
}
BST Shapes

§ The order of supplying the data determines where it is placed in the


BST, which determines the shape of the BST
§ Create BSTs from the same set of data presented each time in a
different order:
a) 17 4 14 19 15 7 9 3 16 10
b) 9 10 17 4 3 7 14 16 15 19
c) 19 17 16 15 14 10 9 7 4 3
BST Operations: Removal

§ removes an item from the BST and adjusts the tree


§ uses a binary search to locate the target item:
§ starting at the root it probes down the tree till it finds the target or
reaches a leaf node (i.e. target not in the tree)
§ removal of a node must not leave a ‘gap’ in the tree,
Removal in BST - Pseudocode

method remove (key)


I if the tree is empty return false
II Attempt to locate the node containing the target using the binary
search algorithm
if the target is not found return false
else the target is found, so remove the node:
Case 1: if the node has 2 empty subtrees
replace the link in the parent with
Case 2: if the node has a left and a right subtree
- replace the node's value with the max(min) value in the
left(right) subtree
- delete the max(min) node in the left(right) subtree recursively
Removal in BST - Pseudocode
Case 3: if the node has no left child
- link the parent of the node to the right (non-empty) subtree

Case 4: if the node has no right child


- link the parent of the target to the left (non-empty) subtree
Removal in BST: Example
Case 1: removing a node with 2 empty subtrees
parent
7

cursor
5 9

4 6 8 10

7
Removing 4
replace the link in the
parent with NULL 5 9

6 8 10
Removal in BST: Example
Case 2: removing a node with 2 subtrees
- replace the node's value with the max value in the left subtree
- delete the max node in the left subtree
What other element
can be used as
Removing 7 replacement?
cursor
cursor

7 6

5 9 5 9

4 6 8 10 4 8 10
Removal in BST: Example
Case 3: removing a node with 1 empty subtree

the node has no left child:


link the parent of the node to the right (non-empty) subtree

parent
parent
7 7
cursor
5 9 cursor 5 9

6 8 10 6 8 10
Removal in BST: Example

Case 4: removing a node with 1 empty subtree


the node has no right child:
link the parent of the node to the left (non-empty) subtree

Removing 5
parent
parent

7 cursor 7
cursor

5 9 5 9

4 8 10 4 8 10
Removal in BST

treeNode * Delete(treeNode *root, int key) { if(succParent != root)


treeNode *temp, *succ, *succParent; succParent->left=succ->right;
if(root==NULL) { printf("Empty Tree"); return root; } else
succParent->right = succ->right;
if(key < root->info) {
root->key=succ->key;
root->left=Delete(root->left, key); return root;} free(succ);
if(key > root->info) { return root;
root->right=Delete(root->right, key); return root; } }
if(root->left == NULL) { }
temp=root->right; free(root); return temp; }
else if(root->right == NULL) {
temp=root->left; free(root); return temp; }
else { // two children
succParent = root;
succ = root->right; // Find successor
while(succ->left != NULL) {
succParent = succ;
succ = succ->left; }
Analysis of BST Operations

§ The complexity of operations search, insert and remove in BST


is O(h) , where h is the height.
§ O(log n) when the tree is balanced. The updating operations
cause the tree to become unbalanced.
§ The tree can degenerate to a linear shape and the operations
will become O(n)
Best Case

BST *root;

insert (root, "E");


insert (root, "C");
insert (root, "D");
insert (root, "A");
insert (root, "H");
insert (root, "F");
insert (root, "K");
>>>> Items in advantageous order:
Output:
K
H
F
E
D
C
A
Worst Case

BST *root;
for (int i = 1; i <= 8; i++)
insert(root, i);

Output: >>>> Items in worst order:


8
7
6
5
4
3
2
1
Random Case

BST *root;
for (int i = 1; i <= 8; i++)
insert(root, random());

Output: >>>> Items in random order:


X
U
P
O
H
F
B
MCQ-1

Postorder traversal of a given binary search tree, T produces the


following sequence of keys
10, 9, 23, 22, 27, 25, 15, 50, 95, 60, 40, 29
Which one of the following sequences of keys can be the result of an
in-order traversal of the tree T?

(A) 9, 10, 15, 22, 23, 25, 27, 29, 40, 50, 60, 95
(B) 9, 10, 15, 22, 40, 50, 60, 95, 23, 25, 27, 29
(C) 29, 15, 9, 10, 25, 22, 23, 27, 40, 60, 50, 95
(D) 95, 50, 60, 40, 27, 23, 22, 25, 10, 9, 15, 29
MCQ-1

Postorder traversal of a given binary search tree, T produces the following


sequence of keys
10, 9, 23, 22, 27, 25, 15, 50, 95, 60, 40, 29
Which one of the following sequences of keys can be the result of an in-
order traversal of the tree T?
(A) 9, 10, 15, 22, 23, 25, 27, 29, 40, 50, 60, 95
(B) 9, 10, 15, 22, 40, 50, 60, 95, 23, 25, 27, 29
(C) 29, 15, 9, 10, 25, 22, 23, 27, 40, 60, 50, 95
(D) 95, 50, 60, 40, 27, 23, 22, 25, 10, 9, 15, 29

Answer: (A)
Explanation: Inorder traversal of a BST always gives elements in increasing
order. Among all four options, a) is the only increasing order sequence.
Better Search Trees

Prevent the degeneration of the BST:


n A BST can be set up to maintain balance during updating
operations (insertions and removals)
n Types of ST which maintain the optimal performance:
n splay trees
n AVL trees
n 2-4 Trees
n Red-Black trees
n B-trees
Binary Search Tree - Best Time

n All BST operations are O(d), where d is tree depth


n minimum d is for a binary tree with N nodes
n What is the best case tree?
n What is the worst case tree?
n So, best case running time of BST operations is O(log2 N)

d  log2N
Binary Search Tree - Worst Time

n Worst case running time is O(N)


n What happens when you Insert elements in ascending order?
n Insert: 2, 4, 6, 8, 10, 12 into an empty BST
n Problem: Lack of “balance”:
n compare depths of left and right subtree
Balanced and unbalanced BST

1 4

2
2 5
3
1 3
4
4
5 Is this “balanced”?
2 6
6

1 3 5 7 7
Motivation

n When building a binary search tree, what type of trees would we


like? Example: 3, 5, 8, 20, 18, 13, 22

3
5 13
8
5 20
13
18 3 8 18 22
20
22
Motivation

n Complete binary tree is hard to build when we allow dynamic


insert and remove.
n We want a tree that has the following properties
n Tree height = O(log(N))

n allows dynamic insert and remove with O(log(N)) time complexity.

n The AVL tree is one of this kind of trees.


8
13
5 18
5 20
3 13 20
3 8 18 22
22
AVL (Adelson-Velskii and Landis) Trees

• An AVL Tree is a binary 3


44
search tree such that for
1 2
every internal node, v of 17 78
T, the heights of the 0 1 0
children of v can differ 32 50 88
by at most 1. 0 0
48 62

An example of an AVL tree where the


heights are shown next to the nodes:
AVL (Adelson-Velskii and Landis) Trees

n AVL tree is a binary search tree with balance condition


n To ensure depth of the tree is O(log(N))
n And consequently, search/insert/remove complexity bound O(log(N))
n Balance condition
n For every node in the tree, height of left and right subtree can differ
by at most 1
Perfect Balance

n Want a complete tree after every operation


n tree is full except possibly in the lower right
n This is expensive
n For example, insert 2 in the tree on the left and then rebuild as a
complete tree

6 5
Insert 2 &
4 9 complete tree 2 8

1 5 8 1 4 6 9
AVL - Good but not Perfect Balance

n AVL trees are height-balanced binary search trees


n Balance factor of a node
n height (left subtree) - height(right subtree)
n An AVL tree has balance factor calculated at every node
n For every node, heights of left and right subtree can differ by no more
than 1
n Store current heights in each node
Node Heights
Tree A (AVL) Tree B (AVL)

height=2 BF=1-0=1 2
6 6
1 0 1 1
4 9 4 9
0 0 0 0 0
1 5 1 5 8

height of node = h
balance factor = hleft-hright
empty height = -1
Node Heights after Insert 7

Tree A (AVL) Tree B (not AVL)


2 balance factor
3
1-(-1) = 2
6 6
1 1 1 2
4 9 4 9
0 0 0 0 0 1 -1
1 5 8 1 5 8

0
7

height of node = h
balance factor = hleft-hright
empty height = -1
Insert and Rotation in AVL Trees

n Insert operation may cause balance factor to become 2 or –2 for


some node
n only nodes on the path from insertion point to root node have possibly
changed in height
n So after the Insert, go back up to the root node by node, updating
heights
n If a new balance factor (the difference hleft-hright) is 2 or –2, adjust
tree by rotation around the node
Single Rotation in an AVL Tree

2 0
6 6
1 2 1 1
4 9 4 8
0 0 1 0 0 0 0
1 5 8 1 5 7 9

0
7
Insertions in AVL Trees

Let the node that needs rebalancing be .


There are four cases:
Require single rotation:
1. Insertion into left subtree of left child of .
2. Insertion into right subtree of right child of .

Require double rotation:


1. Insertion into right subtree of left child of .
2. Insertion into left subtree of right child of .

The rebalancing is performed through four separate rotation algorithms.


Generalizing the Example

12

5 23

2 9 18 30

1 4 7 10
Generalizing the Example

12

5 23

2 9 18 30

1 4 7 10
Generalizing the example

12

X Y
Generalized Single Rotation

k2

k1

Y Z
Generalized Single Rotation

k2

k1

X Y
Single Rotations

Right Rotation

k2 Left Rotation k1

k1 k2

Z X

X Y Y Z
Single Rotations: LL
Inserting into subtree X
k2 destroys the AVL
property at node k2
k1

• Replace node k2 by node k1


Z • Set node k2 to be right child of node k1
• Set subtree Y to be left subtree of
X Y node k2

nnew
AVL Insertion: Single Rotation
k2
Do a “right rotation”

k1
h

Z
h+1 h

X
Single right rotation

k2 Do a “right rotation”

k1
h

Z
h+1 h

X
Single Rotation Completed

k1

k2
h+1

h h

X
Y Z

AVL property has been restored!


Example: Single Rotation: LL
insert(16)
15

8 22

4 10 19 24

3 6 17 20

16
Single Rotations: RR

k2

k1

Y Z

nnew
Example: Single Rotation: RR
insert(26)

15 15

8 22 8 24

4 10 19 24 4 10 22 25

3 6 23 25 3 6 19 23
26
26
AVL Insertion: Double Rotation

Consider a valid k2
AVL subtree

k1
h

h h Z

X Y
AVL Insertion: Double Rotation

Inserting into Y Does “right rotation”


destroys the k2 restore balance?
AVL property
at node j

k1 h

Z
h h+1

Y
AVL Insertion: Inside Case

k1 “Right rotation”
does not restore
balance… now k1 is
out of balance
h k2

X h
h+1

Y
AVL Insertion: Double Rotation

Consider the structure


of subtree Y… k2

k1 h

Z
h h+1

Y
AVL Insertion: Double Rotation

Y = node k3 and k2
subtrees V and W

k1 h

Z
h k3 h+1

X
h or h-1

V W
AVL Insertion: Double Rotation

k2 We will do a left-right
“double rotation” . . .

k1

Z
k3

V W
Double Rotation: First Rotation
k2 left rotation complete

k3

k1 Z

X V
Double rotation: Second Rotation
k2
Now do a right rotation

k3

k1 Z

X
V
Double Rotation: Second Rotation
right rotation complete

Balance has been


k3 restored

k1 k2

h h
h or h-1

X W Z
V
AVL Tree Example:
• Insert 14, 17, 11, 7, 53, 4, 13 into an empty AVL tree

14

11 17

7 53

4
AVL Tree Example:
• Insert 14, 17, 11, 7, 53, 4, 13 into an empty AVL tree

14

7 17

4 11 53

13
AVL Tree Example:
• Now insert 12

14

7 17

4 11 53

13

12
AVL Tree Example:
• Now insert 12

14

7 17

4 11 53

12

13
AVL Tree Example:
• Now the AVL tree is balanced.

14

7 17

4 12 53

11 13
AVL Tree Example:
• Now insert 8

14

7 17

4 12 53

11 13

8
AVL Tree Example:
• Now insert 8

14

7 17

4 11 53

8 12

13
AVL Tree Example:
• Now the AVL tree is balanced.

14

11 17

7 12 53

4 8 13
Delete: Single Rotation
• Consider deepest unbalanced node
– Case 1: Left child’s left side is too high
– Case 4: Right child’s right side is too high
h+2 – The parents may need to be recursively rotated

h+1
Height = h

h/h-1
h Delete Before Deletion
h+1/h+2

h/h+1
h+1
h-1 h
h/h-1 h/h-1 h-1
h

After single rotation


After delete
Delete: Double Rotation
• Consider deepest unbalanced node
– Case 2: Left child’s right side is too high
– Case 3: Right child’s left side is too high
– The parents may need to be recursively rotated

Height = h

Delete Determine all heights


Before Deletion

After Delete After double rotation


AVL Tree Example
Now remove 53

14

11 17

7 12 53

4 8 13
AVL Tree Example
After removal of 53, tree is unbalanced

14

11 17

7 12

4 8 13
AVL Tree Example
Balanced! Then Remove 11

11

7 14

4 8 12 17

13
AVL Tree Example
After removal of 11, 8, which is the largest in its left branch is
replacing 11

11 8

7 14 7 14

4 8 12 17 4 12 17

13 13
AVL Tree Example
Remove 8, tree becomes unbalanced. Then 7, which is the largest
in its left branch is replacing 8

8 7

7 14 4 14

4 12 17 12 17

13
13
AVL Tree Example
So, Removal of 8 amkes tree unbalanced. So make it balanced,
rotation is required

4 12

14

13 17
AVL Tree Example
Balanced!!

12

7 14

4 13 17
C-code to Implement AVL Tree

struct Node { struct Node* createNode(int key) {


int info; struct node *newNode;
struct node *left; newNode=(struct Node*) malloc(sizeof(struct Node));
struct node *right; newNode->info=key;
int ht; newNode->left=NULL;
}; newNode->right=NULL;
int height(struct Node *root) { newNode->ht=0;
if (root == NULL) return -1; return(newNode);
return root->ht; }
}
int max(int x, int y) {
return (x > y)? x : y;
}
C-code to Implement AVL Tree

struct Node *rightRotate(struct Node *root) {


struct Node *k1=root->left;
struct Node *k2=k1->right;
k1->right = root;
root->left = k2;
root->ht=max(height(root->left), height(root->right))+1;
k1->ht = max(height(k1->left), height(k1->right))+1;
return k1;
}
C-code to Implement AVL Tree

struct Node *leftRotate(struct Node *root) {


struct Node *k1=root->right;
struct Node *k2 = k1->left;
k1->left=root;
root->right=k2;
root->ht=max(height(root->left), height(root->right))+1;
k1->ht=max(height(k1->left), height(k1->right))+1;
return k1;
}
int getBalance(struct Node *root) {
if (root == NULL) return 0;
return height(root->left)-height(root->right);
}
C-code to Implement AVL Tree
struct Node* insert(struct Node* root, int key) {
int bal;
if (root == NULL) return(createNode(key));
if (key < root->info)
node->left=insert(root->left, key);
else
root->right=insert(root->right, key);
root->ht=max(height(root->left), height(root->right)) + 1;
bal=getBalance(root);
if (bal > 1 && key < root->left->info)
return rightRotate(root);
if (bal < -1 && key > root->right->info)
return leftRotate(root);
if (bal > 1 && key > root->left->info) {
root->left=leftRotate(root->left);
return rightRotate(root);
}
if (bal < -1 && key < root->right->info) {
root->right=rightRotate(root->right);
return leftRotate(root);
}
return root;
}
C-code to Implement AVL Tree
void preOrder(struct Node *root) {
if(root != NULL) {
printf("%d ", root->info);
preOrder(root->left);
preOrder(root->right);
}
}

int main() {
struct node *root = NULL;
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 25);
printf("Pre order traversal of the constructed AVL tree is \n");
preOrder(root);
return 0;
}
Exercises
n Build an AVL tree with the following values:
15, 20, 24, 10, 13, 7, 30, 36, 25
15, 20, 24, 10, 13, 7, 30, 36, 25
20
15
15 24
20
10
24
13

20 20

13 24 15 24

10 15 13

10
15, 20, 24, 10, 13, 7, 30, 36, 25

20
13
13 24 10 20

10 15 7 15 24

7 30

13 36

10 20

7 15 30

24 36
15, 20, 24, 10, 13, 7, 30, 36, 25

13 13

10 20 10 20

7 15 30 7 15 24

24 36 30

25 13 25 36

10 24

7 20 30

15 25 36
Remove 24 and 20 from the AVL tree.

13 13

10 24 10 20

7 20 30 7 15 30

15 25 36 25 36

13 13

10 30 10 15

7 15 36 7 30

25 25 36
C-code to Implement AVL Tree
struct Node* deleteNode(struct Node* root, int key) {
int bf;
struct Node* temp;
if (root == NULL) return root;
if ( key < root->info)
root->left=deleteNode(root->left, key);
else if( key > root->info)
root->right=deleteNode(root->right, key);
else {
if((root->left==NULL)||(root->right==NULL)) {
temp=root->left?root->left:root->right;
if(temp == NULL) {
temp = root;
root = NULL;
}
else root->info=temp->info; (or *root = *temp)//Copy the content of temp to root
free(temp);
}
else {
temp=maxLSTree(root->left);
root->info=temp->info; // Copy the inorder predecessor's data to this node
root->left=deleteNode(root->left, temp->info); // Delete the inorder predecessor
}
}
C-code to Implement AVL Tree
if (root == NULL) return root;
root->ht=max(height(root->left), height(root->right))+1;
bf=getBalance(root);
if(bf > 1 && getBalance(root->left) >= 0)
return rightRotate(root);
if(bf > 1 && getBalance(root->left) < 0) {
root->left = leftRotate(root->left);
return rightRotate(root);
}
if(bf < -1 && getBalance(root->right) <= 0)
return leftRotate(root);
if(bf < -1 && getBalance(root->right) > 0) {
root->right = rightRotate(root->right);
return leftRotate(root);
}
return root;
}

struct Node* maxLSTree(struct Node* root) {


struct Node* curr = root;
while (curr->right != NULL) curr = curr->right;
return curr;
}
C-code to Implement AVL Tree

int getBalance(struct Node *root) { int main() {


if (root == NULL) return 0; struct Node *root = NULL;
return height(root->left)-height(root->right); root = insert(root, 9);
}
root = insert(root, 5);
int height(struct Node *root) { root = insert(root, 10);
if (root == NULL) return 0; root = insert(root, 0);
return root->ht; root = insert(root, 6);
}
root = insert(root, 11);
void preOrder(struct Node *root) { root = insert(root, -1);
if(root != NULL) { root = insert(root, 1);
printf("%d ", root->info); root = insert(root, 2);
preOrder(root->left); printf("\nPre order traversal after
deletion of 10 \n");
preOrder(root->right);
preOrder(root);
}
return 0;
}
}
Pros and Cons of AVL Trees
Arguments for AVL trees:
1. Search is O(log n) since AVL trees are always balanced.
2. Insertion and deletions are also O(log n)
3. The height balancing adds no more than a constant factor to the speed of
insertion.
Arguments against using AVL trees:
1. Difficult to program & debug; more space for balance factor.
2. Asymptotically faster but rebalancing costs time.
3. Most large searches are done in database systems on disk and use other
structures (e.g. B-trees).
Threaded Binary Tree
Threaded Binary Tree
n Inorder traversal of a Binary tree can either be done using
recursion or with the use of a auxiliary stack.
n The idea of threaded binary trees is to make inorder traversal
faster and do it without stack and without recursion.
n A binary tree is made threaded by making all right child pointers
that would normally be NULL point to the inorder successor of the
node (if it exists).
Threaded Binary Tree
There are two types of threaded binary trees.
n Single Threaded: Where a NULL right pointers is made to point to
the inorder successor (if successor exists)
n Double Threaded: Where both left and right NULL pointers are
made to point to inorder predecessor and inorder successor
respectively.
n The predecessor threads are useful for reverse inorder traversal and
postorder traversal.
n The threads are also useful for fast accessing ancestors of a node.
Threaded Binary Tree
• In this binary tree, out of 12
n In a linked representation of a pointers there are 7 NULL pointers
binary tree, # NULL pointers are & 5 non-NULLpointers.
more than non-NULL pointers. • In a n node binary tree, (n+1)
n Consider the following binary tree: NULL pointers out of 2×n pointers.
• The threaded binary tree makes
effective use of these NULL
pointers.
• A. J. perils & C. Thornton jointly
proposed idea to make effective
use of these NULL pointers.
• All the NULL pointers are replaced
by the appropriate pointer values
called threads.
Threaded Binary Tree
n And binary tree with such pointers are called threaded binary tree.
n In the threaded binary tree, it is necessary to distinguish between a
normal pointer and a thread.
n The node representation for a threaded binary tree contains five
fields which is shown below:
Threaded Binary Tree

• One may choose a one-way threading or single theading (left-


threaded binary tree, right-threaded binary tree), a two-way
threading or double threading.
• Here, the threading will correspond to the inorder traversal of T.
Threaded Binary Tree: One-Way
n In the one way threading of T, a
thread will appear in the right
field of a node and will point to
the next node in the in-order
traversal of T.
n Example of one-way in-order
threading.

Inorder of the tree: D, B, F, E, A, G, C, L, J, H, K


Threaded Binary Tree: Two-Way
In the two-way threading of T.
n A thread will also appear in the left field of a node and will point to the
preceding node in the in-order traversal of tree T.
n Furthermore, the left pointer of the first node and the right pointer of the
last node (in the in-order traversal of T) will contain the NULL value.
Threaded Binary Tree
n The figure shows two-way in-
order threading.
n Here, right pointer=next node
of in-order traversal and left
pointer=previous node of in-
order traversal
n Inorder traversal tree: D, B, F,
E, A, G
Threaded Binary Tree
Two-way Threading with Header node
n Again two-way threading has left pointer of
the first node and right pointer of the last
node (in the inorder traversal of T) will
contain the NULL value when T will point to
the header nodes is called two-way threading
with header node threaded binary tree.
n This figure explains two-way threading with
header node.
Threaded Binary Tree
n Example of link
representation of
threading binary
tree.
n In-order traversal :
G, F, B, A, D, C, E
Threaded Binary Tree
Advantages of threaded binary tree
n The traversal operation is more faster than that of its unthreaded
version
n non-recursive implementation of threaded binary tree can run faster and
n does not require the botheration of stack management
n Determining the predecessor and successor nodes starting from any
node is efficient.
n In case of unthreaded binary tree, this task is more time consuming and
difficult because a stack is required to provide upward pointing
information
n whereas in a threaded binary tree, without using the stack the same can
be carried out with the threads.
Threaded Binary Tree
Advantages of threaded binary tree
n Any node can be accessible from any other node.
n Threads are usually move to upward whereas links are downward.
n Thus in a threaded tree, one can move in their direction and nodes are
in fact circularly linked.
n But in unthreaded tree one can move only in downward direction
starting from root.
n Insertion into and deletions from in a threaded tree are although
time consuming operations but these are very easy to implement.
Threaded Binary Tree
Disadvantages of threaded binary tree
n Insertion and deletion from a threaded tree are very time
consuming operation compare to non-threaded binary tree.
n This tree require additional bit to identify the threaded link.
Threaded Binary Tree
C Structure

struct node {
struct node *left;
boolean lthread;
int info;
boolean rthread;
struct node *right;
};
Threaded Tree Traversal Code
struct node *insert(struct node *root, int ikey) { if(ptr->rthread == false)
struct node *tmp, *par, *ptr; ptr = ptr->right;
int found=0; else
ptr = root; break;
par = NULL; }
while(ptr!=NULL) { }
if(ikey == ptr->info) { if(found)
found =1; printf("\nDuplicate key");
break; else {
} tmp=(struct node *)malloc(sizeof(struct
par = ptr; node));
if(ikey < ptr->info) { tmp->info=ikey;
if(ptr->lthread == false) tmp->lthread = true;
ptr = ptr->left; tmp->rthread = true;
else if(par==NULL) {
break; root=tmp;
} tmp->left=NULL;
else { tmp->right=NULL;
}
Threaded Tree Traversal Code
else if(ikey < par->info) {
tmp->left=par->left;
tmp->right=par;
par->lthread=false;
par->left=tmp;
}
else {
tmp->left=par;
tmp->right=par->right;
par->rthread=false;
par->right=tmp;
}
}
return root;
}
Threaded Tree Traversal Code
if(ptr->rthread == false)
ptr = ptr->right;
struct node *del(struct node *root, int dkey) {
else
struct node *par,*ptr;
break;
int found=0;
}
ptr = root;
}
par = NULL;
if(found==0)
while(ptr!=NULL) {
printf("\ndkey not present in tree");
if(dkey == ptr->info) {
else if(ptr->lthread==false && ptr-
found =1;
>rthread==false) /*2 children*/
break;
root = case_c(root, par, ptr);
}
else if(ptr->lthread==false) /*only left
par = ptr;
child*/
if(dkey < ptr->info) {
root = case_b(root, par, ptr);
if(ptr->lthread == false)
else if(ptr->rthread==false) /*only right
ptr = ptr->left;
child*/
else
root = case_b(root, par, ptr);
break;
else /*no child*/
}
root = case_a(root, par, ptr);
else {
return root;
}
Threaded Tree Traversal Code
struct node *case_a(struct node *root, struct node *par, struct node *ptr) {
if(par==NULL) /*root node to be deleted*/
root=NULL;
else if(ptr==par->left) {
par->lthread=true;
par->left=ptr->left;
}
else {
par->rthread=true;
par->right=ptr->right;
}
free(ptr);
return root;
}
Threaded Tree Traversal Code
struct node *case_b(struct node *root, struct node *par, struct node *ptr) {
struct node *child,*s,*p;
/*Initialize child*/
if(ptr->lthread==false) /*node to be deleted has left child */
child=ptr->left;
else /*node to be deleted has right child */
child=ptr->right;
if(par==NULL) /*node to be deleted is root node*/
root=child;
else if(ptr==par->left) /*node is left child of its parent*/
par->left=child;
else /*node is right child of its parent*/
par->right=child;
s=in_succ(ptr);
p=in_pred(ptr);
if(ptr->lthread==false) /*if ptr has left subtree */
p->right=s;
else {
if(ptr->rthread==false) /*if ptr has right subtree*/
s->left=p;
}
free(ptr);
return root;
}
Threaded Tree Traversal Code
struct node *case_c(struct node *root, struct node *par, struct node *ptr) {
struct node *succ,*parsucc;
/*Find inorder successor and its parent*/
parsucc = ptr;
succ = ptr->right;
while(succ->left!=NULL) {
parsucc = succ;
succ = succ->left;
}
ptr->info = succ->info;
if(succ->lthread==true && succ->rthread==true)
root = case_a(root, parsucc,succ);
else
root = case_b(root, parsucc,succ);
return root;
}
Threaded Tree Traversal Code
struct node *in_succ(struct node *ptr) {
if(ptr->rthread==true)
return ptr->right;
else {
ptr=ptr->right;
while(ptr->lthread==false)
ptr=ptr->left;
return ptr;
}
}

struct node *in_pred(struct node *ptr) {


if(ptr->lthread==true)
return ptr->left;
else {
ptr=ptr->left;
while(ptr->rthread==false)
ptr=ptr->right;
return ptr;
}
}
Threaded Tree Traversal Code
void preorder(struct node *root ) {
struct node *ptr;
void inorder( struct node *root) { if(root==NULL) {
struct node *ptr; printf("Tree is empty");
if(root == NULL ) { return;
printf("Tree is empty"); }
return; ptr=root;
} while(ptr!=NULL) {
ptr=root; printf("%d ", ptr->info);
/*Find the leftmost node */ if(ptr->lthread==false)
while(ptr->lthread==false) ptr=ptr->left;
ptr=ptr->left; else if(ptr->rthread==false)
while(ptr!=NULL) { ptr=ptr->right;
printf("%d ",ptr->info); else {
ptr=in_succ(ptr); while(ptr!=NULL && ptr->rthread==true)
} ptr=ptr->right;
}/*End of inorder( )*/ if(ptr!=NULL)
ptr=ptr->right;
}
}
}/*End of preorder( )*/
Threaded Tree Traversal

8
3

1 5 7 11

9 13
Threaded Tree Traversal
Output
6 1

8
3

1 5 7 11

9 13

Start at leftmost node, print it


Threaded Tree Traversal
Output
1
6
3

8
3

1 5 7 11

9 13
Follow thread to right, print node
Threaded Tree Traversal
Output
6 1
3
5
8
3

1 5 7 11

9 13
Follow link to right, go to leftmost
node and print
Threaded Tree Traversal
Output
1
6
3
5
8 6
3

1 5 7 11

9 13
Follow thread to right, print node
Threaded Tree Traversal
Output
6
1
3
8 5
3 6
7
1 5 7 11

9 13

Follow link to right, go to leftmost


node and print
Threaded Tree Traversal
Output
6 1
3
5
8
3 6
7
8
1 5 7 11

9 13

Follow thread to right, print node


Threaded Tree Traversal
Output
6 1
3
5
8 6
3
7
8
1 5 7 11 9

9 13

Follow link to right, go to leftmost


node and print
Threaded Tree Traversal
Output
6 1
3
5
8
3 6
7
8
1 5 7 11 9
11

9 13

Follow thread to right, print node


Threaded Tree Traversal
Output
6 1
3
5
8 6
3
7
8
1 5 7 11 9
11
13
9 13
Follow link to right, go to leftmost
node and print

You might also like